Case statement not working with or condition - mysql

Please help me with this code.
SELECT (CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN ('7' OR '8') THEN 'SA'
END) `REGION`,
This is the result:
Region
null
MM
The result should be like this:
Region
SA
MM

The following syntax is not valid:
WHEN ('7' OR '8') THEN 'SA'
What follows WHEN or ELSE using this style of CASE expression can only be a literal value, not a logical expression. So, you could refactor to:
SELECT
CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN '7' THEN 'SA' -- repeat the 'SA' predicate twice
WHEN '8' THEN 'SA' END AS REGION
FROM yourTable;
If you wanted to combine the 7 and 8 cases in a single WHEN, then you would have to use the longer form of CASE:
SELECT
CASE WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) = '7' OR
LEFT(BRANCH_CODE, 1) = '8' THEN 'SA' END AS REGION
FROM yourTable;
This second version is fairly ugly IMHO, and I would probably stick with the first version, which just repeats the SA predicate in two places.

I had similar issues when trying to apply multiple condition statements in "CASE" statement.
I solved it by moving the test after the "WHEN" statement as following :
SELECT (CASE
WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) IN ('7' OR '8') THEN 'SA'
END) `REGION`,

Related

mysql error: FUNCTION asterisk.SUM does not exist. (Apache superset)

I connected the mysql database and ran a direct sql query and I got the correct table, I wanted to visualize it and clicked the "Explore" button, but I got the error: "mysql error: FUNCTION asterisk.SUM does not exist. Check the ' Function Name Parsing and Resolution 'section in the Reference Manual "Please tell me where I made a mistake, thanks.
working sql request
error
My sql request:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)),'%H:%i:%S') AS Call_duration,
case
when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-start > 0
group by DATE_FORMAT(start, '%Y-%m-%d'), 4
order by 1 desc
My request works correctly, but when I try to create a chart, superset changes the request and it has a line break after SUM. Сan I fix this without changing the database configuration?
Superset out query:
SELECT `Date` AS `Date`,
`Type` AS `Type`,
`Call_duration` AS `Call_duration`,
`Operator` AS `Operator`,
`Number_of_calls` AS `Number_of_calls`
FROM
(SELECT DATE_FORMAT
(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM
(end-start)), '%H:%i:%S') AS Call_duration,
case
when substring(dstchannel, 5, 4) = '1000' then 'Name1'
when substring(dstchannel, 5, 4) = '2000' then 'Name2'
when substring(dstchannel, 5, 4) = '3000' then 'Name3'
when substring(dstchannel, 5, 4) = '4000' then 'Name4'
when substring(dstchannel, 5, 3) = '100' then 'Other'
end AS
Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-
start > 0
group by DATE_FORMAT
(start, '%Y-%m-%d'),
4
order by 1 desc) AS expr_qry
LIMIT 1000;
Your group by doesn't match the select columns. Try:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)), '%H:%i:%S') AS Call_duration,
(case when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end) AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in' AND
disposition = 'ANSWERED'
end > start
group by DATE_FORMAT(start, '%Y-%m-%d'), type, call_duration, operator
order by 1 desc

Update two tables at once, using values from first table

So I need to Update table scores and use the updated value of column won to update the second table tbl_users. So far the code updates scores, but uses the old value of won for the second table update:
UPDATE scores a
left join tbl_users b on
a.uid = b.userID
SET a.won = CASE
WHEN a.nright = '0' THEN '0'
WHEN a.nright = '1' THEN '25'
WHEN a.nright = '2' THEN '50'
WHEN a.nright = '3' THEN '100'
WHEN a.nright = '4' THEN '200'
WHEN a.nright = '5' THEN '400'
WHEN a.nright = '6' THEN '700'
WHEN a.nright = '7' THEN '1000'
END,
b.pts=b.pts+a.won,
b.pts_total=b.pts_total+a.won
WHERE a.uid=$user AND b.userID=$user
What you want to do is explicitly documented as correct:
The second assignment in the following statement sets col2 to the
current (updated) col1 value, not the original col1 value. The result
is that col1 and col2 have the same value. This behavior differs from
standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
I assume that the issue is the multi-table update, where the set pulls the value from the earlier table.
You may be able to fix this using variables. I am not 100% sure, but the following is worth a try:
UPDATE scores s JOIN
tbl_users u
ON s.uid = .uuserID
SET s.won = (#w := (CASE WHEN s.nright = '0' THEN '0'
WHEN s.nright = '1' THEN '25'
WHEN s.nright = '2' THEN '50'
WHEN s.nright = '3' THEN '100'
WHEN s.nright = '4' THEN '200'
WHEN s.nright = '5' THEN '400'
WHEN s.nright = '6' THEN '700'
WHEN s.nright = '7' THEN '1000'
END)
),
u.pts = u.pts + #w,
u.pts_total = u.pts_total + #w
WHERE s.uid = $user ;
The documentation strongly suggests that the set clauses are processed in order for a single table. Alas, it is not clear whether this is always true for multiple tables.
If not, you can use two updates.

mysql combining two tables to produce the following output

hello i had ask the same question before but i want another way. we can use locate and max function to solve the question. but my teacher told me to do like this
my code is like this when '0' then '1' else '0'
select u.id, u.name,
case f.finger when '0' then '1' else '0' end as '0',
case f.finger when '1' then '1' else '0' end as '1',
case f.finger when '2' then '1' else '0' end as '2',
case f.finger when '3' then '1' else '0' end as '3',
case f.finger when '4' then '1' else '0' end as '4',
case f.finger when '5' then '1' else '0' end as '5'
from users u left join user_fingerprints f
on u.id= f.user_id
the code above will resulted in 8 rows.
then i need to combine the rows so that the rows with the same id combine to produce this
from that result then use case function. when the value is 1 then y. when value is zero then n.
can someone give me the answer without the use of max function? thanks
the table and result
You can also do it with SUM() and another CASE EXPRESSION :
SELECT t.id,t.name,
CASE WHEN t.`0` > 0 THEN 'Y' ELSE 'N' as `0`
CASE WHEN t.`1` > 0 THEN 'Y' ELSE 'N' as `1`
....
FROM (
SELECT u.id,u.name,
SUM(CASE WHEN f.finger = '0' then '1' else '0' end) as `0`,
SUM(CASE WHEN f.finger = '1' then '1' else '0' end) as `1`,
....
from users u left join user_fingerprints f
on u.id= f.user_id
GROUP BY u.id,u.name) t

my mysql SELECT case can't return 3 columns

I'm trying to return 3 columns with the query below. the current query works fine.
SELECT cat, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat
ORDER BY CAST(cat AS UNSIGNED) ASC
when i try and return another column cat_type i get an error
SELECT cat, cat_type, COUNT(*) as count FROM ....
The error i get is
#1054 - Unknown column 'cat_type' in 'field list'
but cat_type does exist in my ab table. any idea what i'm missing? Thanks
Your cat_type exists in ab table.
But your ab table does not exists in your main select.
It only exists within the sub query which returns someRandomAliasHere to you.
So you should likely select cat_type from the same select as you select your cases.
Then you should have access to it, but it would then likely mess with your group by / count.
You'll properly need a more advanced query for what you're after.
You need to include cat_type in the subquery. I would recommend:
SELECT cat, cat_type, COUNT(*) as count
FROM (SELECT (case WHEN `cat_type` = 'PREMIUM' then 1
WHEN `cat_type` = 'NOT PREMIUM' then 2
WHEN `cat_type` = 'GOLD' then 3
WHEN `cat_type` = 'EXECUTIVE' then 4
WHEN `cat_type` = 'NOT PROVIDED' then -1
else -2
end) AS cat, *
FROM `ab` AS s JOIN
`make` AS m
USING (make_code)
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY abs(cat) asc
Note the following:
Added * to the subquery to capture all the columns.
Changed the join syntax. Not only are explicit joins better but the using clause allows the use of * without having to worry about duplicate names among the joined column.
Removed the single quotes from the constant values for cat. You are treating these as numbers in the order by, so use numbers for the values.
Changed the order by to abs() rather than casting to unsigned. However, do you really want unsigned here?
You're not selecting cat_type into someRandomAliasHere, hence it's not available to your main select. This should fix it:
SELECT cat, cat_type, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat, cat_type FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY CAST(cat AS UNSIGNED) ASC
You needed to include the column in subquery first and then reference that using the table.col
Try below
SELECT someRandomAliasHere.cat_type, cat, COUNT(*) as count FROM
(SELECT cat_type, case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat
ORDER BY CAST(cat AS UNSIGNED) ASC
You need to also select the column cat_type, so that someRandomAliasHere owns the column.
SELECT cat, cat_type, COUNT(*) as count FROM
(SELECT case WHEN `cat_type` = 'PREMIUM' then '1'
WHEN `cat_type` = 'NOT PREMIUM' then '2'
WHEN `cat_type` = 'GOLD' then '3'
WHEN `cat_type` = 'EXECUTIVE' then '4'
WHEN `cat_type` = 'NOT PROVIDED' then '-1'
else '-2'
end AS cat, cat_type FROM `ab` AS s
JOIN `make` AS m
WHERE s.make_code = m.make_code
) AS someRandomAliasHere
GROUP BY cat, cat_type
ORDER BY CAST(cat AS UNSIGNED) ASC
Dont forget to add cat_type in GROUP BY too.

MySQL Order By With Grades As String But Want Integer

I want to order grades that are a string in the following order.
K, 1, 2, 4, .... 12
But I keep getting 5, 4, 3, ... 12, K, 1
The grade column in sims_classroom is VARCHAR(255) and the table is latin1;
I have tried every cast and trick in the book. At the moment I have the following trick by adding 0 to it. What am I doing wrong?
SELECT
(SELECT district_get_name_function(sod.parent_id, sod.id)) AS 'district_name',
(SELECT school_get_name_function(so.id)) AS 'school_name',
st.teacher_username,
st.teacher_first_name,
st.teacher_last_name,
c.name as 'classroom_name',
c.grade,
c.id,
d.name AS 'discipline_name',
d.id AS 'discipline_id',
lc.name AS 'program_name',
lc.id AS 'program_id'
FROM sims_classroom c
.
.
.
ORDER BY
CASE lower(sort_direction) WHEN 'asc' THEN
CASE lower(sort_order)
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN 0
ELSE (c.grade + 0)
END
WHEN 'teachername' THEN lower(st.teacher_first_name)
ELSE c.name
END
END ASC,
CASE lower(sort_direction) WHEN 'desc' THEN
CASE lower(sort_order)
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN 10000
ELSE (c.grade + 0)
END
WHEN 'teachername' THEN lower(st.teacher_first_name)
ELSE c.name
END
END DESC
You could create a lookup table for the grades. It would have the Grade_Name (i.e. 'K','1','2', etc) and a Grade_Order as an int.
You'd have records like this:
Grade_Name Grade_Order
K 1
1 2
2 3
3 4
and so on.
Then you can add that lookup table to your JOIN and ORDER BY Grade_Order.
I could only get it to work doing this.
WHEN 'grade' THEN
CASE c.grade
WHEN 'K' THEN '00'
WHEN '9' THEN '09'
WHEN '8' THEN '08'
WHEN '7' THEN '07'
WHEN '6' THEN '06'
WHEN '5' THEN '05'
WHEN '4' THEN '04'
WHEN '3' THEN '03'
WHEN '2' THEN '02'
WHEN '1-2' THEN '01'
WHEN '1' THEN '01'
ELSE c.grade
END