Spark sql: query with case and thousands of columns - mysql

I had a table with two thousands columns. i need to modify few columns data based on flag column.
tableSchemaRDD.registerAsTable("customer")
var results = sqlContext.sql("select *,case when flag1 = 'A' then null else charges end as charges, flag2 = 'B' then null then else stax end as stax from customer")
flag1,flag2, charges,stax are the columns from my table. the above code will give extra two coumns along with original columns. How can i get all columns with modified columns (charges,stax) based on flag columns.

Don't use asterisk ( * ), actually asterisk tells you have to bring all columns, after that you are using the two cases which are responsible for two new columns. You just have to remove asterisk ( * ) and place the column names comma separated without those column names which you are going to modify. In this way those two old columns will not be shown.
If you are using Spark 1.3 then its very easy for DataFrame, like
val columsNames = df.schema.fieldNames
.filter(fieldName => {
!fieldName.equals("charges") && !fieldName.equals("stax")
}).mkString(",")
Don't exactly remember that there are methods/properties in SchemaRDD or not.
EDITED:
Just understand the issue, asterisk tells bring all old columns, then you are using two new cases (two new columns.) also, where in your scenario you have to specify columns with their names without charges and stax, as these are your new columns, those will be populated by cases.
Suppose you have a table customer which has 4 columns, id name charges stax and you write the query like you are writing
select *,case when flag1 = 'A' then null else charges end as charges, flag2 = 'B' then null then else stax end as stax from customer
This will give you 6 columns, 4 for asterisk ( * ) as there are four columns in the table. and 2 for your cases. Instead of asterisk ( * ), you have to query like
select id , name ,case when flag1 = 'A' then null else charges end as charges, flag2 = 'B' then null then else stax end as stax from customer
This will result in 4 columns, id, name as they are (OLD). Stax and Charges (new) result of your cases.
Hopefully this will help.

Related

Count empty text fields in CASE sentence in MySQL

My column contains categories A, B, C or "empty" ( which means the record is not categorized).
I want to show the total number of A's, B's and C's and the total number of records "Not categorized", and have tried the query below.
It does not work, however. It shows the correct number of A, B and C's but not the number of not categorized.
SELECT count(*) AS Quantity,
CASE
WHEN cf_ab_contacts.col_621 = '' THEN "Uncategorized"
ELSE cf_ab_contacts.col_621
END AS `Category`
FROM ...
WHERE ...
GROUP BY `cf_ab_contacts`.`col_621`;
Thanks for all help.
I'm really sorry - but the query did work as intended - there was an error in my WHERE section which excluded empty columns.
Thanks to Ankit for your patience.
I'm not sure if I can delete this thread - I should never have posted it in the first place.
Considering By Empty you mean NULL not a single space value, You have to test the condition with IS NULL predicate -
SELECT count(*) AS Quantity,
CASE
WHEN cf_ab_contacts.col_621 IS NULL THEN "Uncategorized"
ELSE cf_ab_contacts.col_621
END AS `Category`
FROM ...
WHERE ...
GROUP BY CASE
WHEN cf_ab_contacts.col_621 IS NULL THEN "Uncategorized"
ELSE cf_ab_contacts.col_621
END;

Best way to store configuration in MySQL

I have a scenario where i need to store configurations in mysql table having three columns namely VendorID,ServiceID and ModeID . Configuration for a vendor can be done with three overriding cases as follows.
One column VendorID having non-NULL value with ServiceID ,ModeID having NULL value.
VendorID,ServiceID,ModeID -- > 1,NULL,NULL
Two columns VendorID,ServiceID having non-NULL values with ModeID having NULL value.
VendorID,ServiceID,ModeID -- > 1,1,NULL
All three columns having non NULL values.
VendorID,ServiceID,ModeID -- > 1,1,1
When case 1,2,3 are defined and in the MySQL query WHERE clause vendorid,servideid and modeid are passed, then case 3 overrides case 2 and case 1.
When case 3 is not defined and case 1,2 are defined and in the MySQL query WHERE clause vendorid,servideid and modeid are passed, then case 2 overrides case 1.
When case 3 and case 2 are not defined and case 1 is defined and in the MySQL query WHERE clause vendorid,servideid and modeid are passed, then case 1 is returned.
Now my question is, how can i query the table to get the configuration returned when vendorid,servideid and modeid are passed in the query in one go without having to query 3 times separately.
Any other good approach for the above problem is also welcome.
You may want this:
where (VendorID, ServiceID, ModelID) = ($VendorID, $ServiceID, $ModelID) or
( (VendorID, ServiceID) = ($VendorID, $ServiceID) and ModelId is null) or
( VendorID = $VendorID and ServiceID is null and ModelId is null)
Alternatively you may want:
select t.*
from t
where VendorId = $VendorId and
(ServiceId = $ServiceId or ServiceId is null) and
(ModelId = $ModelId or ModelId is null)
order by ( ServiceId is not null ) desc,
( ModelId is not null ) desc
limit 1;
This returns one row with the best match.

check for values in MySQL but within a specific range

I am a beginner in MySQL and i want to do a check for values but within a range, i have this:
SELECT t1.width, COUNT( t1.width )
FROM test t1
INNER JOIN (
SELECT t2.width
FROM test t2
GROUP BY width
HAVING COUNT( t2.width ) >1
)t2 ON t1.width BETWEEN (t2.width +1000) AND (t2.width -1000)
ORDER BY t1.width
So what i want to do is to check if there is two values of 'width' with a difference of +1000 or -1000.
The result is always null.
could you please tell me what is wrong with the query?
I don't fully understand what your data is. The way I understand is you are looking to see if two values from two columns have a specific difference, i.e the first value in the first column is 2000 and the first value in the second column is 1000, since there is a difference of 1000 you want this noted. You could use the CASE function (more detail here https://www.w3schools.com/sql/func_mysql_case.asp).
Say you have one column called width_1 which consists of different values of widths, and a second column called width_2 which also consists of different width values, all contain in a table called width_table, you could use the following:
SELECT
CASE
WHEN width_1 - width_2 = 1000 OR width_1 - width_2 = -1000 THEN TRUE
ELSE FALSE
END AS column_name
FROM width_table ;
This will produce a column whose entries are either 1 if the difference is exactly +1000 or -1000, or 0 if the difference is anything else.
If you want to check if the difference is between 1000 and -1000, then you can use the following:
SELECT
CASE
WHEN width_1 - width_2 BETWEEN -1000 AND 1000 THEN TRUE
ELSE FALSE
END AS column_name
FROM width_table ;

Update column based on value in another table without joins

Up front, I'm in a DB class and could use a hint to get closer to the correct answer.
In the ticket_old table there is the first and last name of technicians. Only two unique names.
In the new ticket table, I've got a tech_id column which needs the int matching the last_name of the tech found in the ticket_old table.
I've been trying to do this using the code below, which executes successfully and updates 0 rows.
UPDATE ticket,ticket_old
SET tech_id = (CASE WHEN ticket_old.techLast = 'name1' THEN 1
WHEN ticket_old.techLast = 'name2' THEN 2
END)
;
-edit, I also tried the following which runs and updates 0 rows.
UPDATE ticket,
(SELECT techLast FROM ticket_old WHERE techLast = 'name1') as src
SET ticket.tech_id = 1;
When Comparing two values,
Always use Double Equal marks:
SET tech_id = (CASE WHEN ticket_old.techLast == 'name1' THEN 1
WHEN ticket_old.techLast == 'name2' THEN 2
END)
I'm not sure if it is 'name' or "name". Try it.

Inner join A on B if B not empty, else A

Two tables:
prefix ( id, value )
---------------------
1 'hello'
2 'good afternoon'
3 'good night'
suffix ( id, value )
---------------------
1 'world'
3 'world'
I'd like to get
all from table prefix which can be joined on table suffix via id
result should look like:
prefix.id prefix.value
--------------------------
1 'hello'
3 'good night'
well - quite easy so far...
but if table suffix is empty I'd like everything from table prefix
without subselects/ctes or if.... and in one query fulfilling both conditions!
Is there any trick to get this done by some magic having-clause or tricky something else?
Just for testcases: SQL-fiddle
Well, there is a way, but I agree with others that your requirements make no (practical) sense.
Anyway, here you go:
Join the suffix table twice (each time with a left join). One join is on the id column, the other on an always true condition.
Group the results on the prefix columns you want in the output and at least one non-nullable column of the first instance of suffix.
In the HAVING clause, put a condition that the first suffix column is not null or the number of values of a non-nullable column in the second suffix instance is 0. (Obviously, every group will have the same number of rows, i.e. the count will be the same for every prefix row.)
This is the query:
SELECT prefix.id, prefix.value
FROM prefix
LEFT JOIN suffix ON prefix.id = suffix.id
LEFT JOIN suffix AS test ON 1=1
GROUP BY prefix.id, prefix.value, suffix.id
HAVING suffix.id IS NOT NULL OR COUNT(test.id) = 0;
And there's also a demo at SQL Fiddle.
You need an OR and NOT EXISTS:
SELECT
prefix.id, prefix.value
FROM
prefix
WHERE
EXISTS(SELECT 1 from suffix WHERE prefix.id=suffix.id)
OR NOT EXISTS(SELECT 1 FROM suffix)
Demo
I guess the answer is: no, you can't!
Or if you can: No, you shouldn't.