SQL - Giving AS keyword in UPDATE Statement - mysql

I have the following UPDATE statement:
update MESSAGES set status=
(select (CASE
WHEN from_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'S'
WHEN status='R'
THEN 'D'
END)
WHEN to_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'R'
WHEN status='S'
THEN 'D'
END)
END)
as status_value)
where primary_key='236499681204'
and status_value not null ;
The problem with this query is, at the last line, status_value is not recognized. If I remove the last comparison, and status_value not null, it works. I dint expect the above version to work, but could someone tell me an alternative that would achieve the same?
Is there a way I can use the AS keyword in the UPDATE query to define the variable status_value?
Edit
The actual requirement is not just that i check if status_value is null, but also that I dont perform any update if it is null

Try to add ELSE STATUS and remove and status_value not null:
update MESSAGES set status=
(select (CASE
WHEN from_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'S'
WHEN status='R'
THEN 'D'
END)
WHEN to_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'R'
WHEN status='S'
THEN 'D'
END)
ELSE STATUS
END)
as status_value)
where primary_key='236499681204';
You can also try to use view
create view MyView as
select (CASE
WHEN from_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'S'
WHEN status='R'
THEN 'D'
END)
WHEN to_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'R'
WHEN status='S'
THEN 'D'
END)
END)
as status_value;
update MESSAGES set status= mv.status_value
from MyView mv
where primary_key='236499681204'
and mv.status_value is null
or you can use case in condition
update MESSAGES set status=
(select (CASE
WHEN from_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'S'
WHEN status='R'
THEN 'D'
END)
WHEN to_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'R'
WHEN status='S'
THEN 'D'
END)
END)
as status_value)
where primary_key='236499681204'
and CASE
WHEN from_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'S'
WHEN status='R'
THEN 'D'
END)
WHEN to_id='111111111'
THEN (CASE
WHEN status='A'
THEN 'R'
WHEN status='S'
THEN 'D'
END)
END is not null;

assuming all you want is to get rid of the null, you can do this:
update MESSAGES set status=
IFNULL(
(CASE WHEN from_id='111111111' THEN
(CASE WHEN status='A' THEN 'S'
WHEN status='R' THEN 'D' END)
WHEN to_id='111111111' THEN
(CASE WHEN status='A' THEN 'R'
WHEN status='S' THEN 'D' END) END),
status)
where primary_key='236499681204' ;

It seems to me that you're trying to do a sub-query for the update statement, when I don't think it's really all that necessary.
You can simplify the query a bit like this:
UPDATE MESSAGES
SET status = CASE
WHEN
(from_id='111111111' AND status='A') THEN 'S'
WHEN
(to_id ='111111111' AND status='A') THEN 'R'
WHEN
(from_id ='111111111' AND status='R') OR
(to_id ='111111111' AND status='S') THEN 'D'
ELSE status
END
WHERE priamry_key = '236499681204'

Related

Count each day with SQL query

I want to display a table with SQL query like this:
I have run my query:
select
tb_r_orderdata.finishtime as date ,
count(*)sum all,
sum(when status = 'SUCCESS' and issync = '1' then 1 else 0 end) sumpaid,
sum(when status = 'SUCCESS' and issync in ('3', '4') then 1 else 0 end) sumfail,
sum(when status = 'CLOSED' then 1 else 0 end) sumclose,
sum(when status = 'Null' then 1 else 0 end) sumunflag
from
tb_r_orderdata;
But when I execute it, the result is different than what I expected. The result is like this:
Thank you for any help
You are missing the GROUP BY and the CASE:
select tb_r_orderdata.finishtime as date ,
COUNT(*) as sumall,
SUM(CASE WHEN status='SUCCESS' AND issync='1' then 1 ELSE 0 END) as sumpaid,
SUM(CASE WHEN status='SUCCESS' AND issync in ('3','4') then 1 ELSE 0 END) as sumfail,
SUM(CASE WHEN status='CLOSED' then 1 ELSE 0 END) as sumclose,
SUM(CASE WHEN status is null then 1 ELSE 0 END) as sumunflag
from tb_r_orderdata
group by tb_r_orderdata.finishtime ;
MySQL treats booleans as integers in a numeric context, with "1" for true and "0" for false. You can simplify your query to:
select o.finishtime as date ,
COUNT(*) as sumall,
SUM(status = 'SUCCESS' AND issync = '1') as sumpaid,
SUM(status = 'SUCCESS' AND issync in ('3', '4')) as sumfail,
SUM(status = 'CLOSED') as sumclose,
SUM(status is null) as sumunflag
from tb_r_orderdata o
where tb_r_orderdata.finishtime is not NULL
group by o.finishtime ;
This also removes NULL finish times.
Explanation in comment for Gordon Linoff
i have try your answer but there is record NULL in the top of table, i dont know why, can you explain it
with little bit change from Gordon Linoff answer
select tb_r_orderdata.finishtime as date ,
SUM(CASE WHEN status='SUCCESS' AND issync='1' then 1 ELSE 0 END) as sumpaid,
SUM(CASE WHEN status='SUCCESS' AND issync in ('3','4') then 1 ELSE 0 END) as sumfail,
SUM(CASE WHEN status='CLOSED' then 1 ELSE 0 END) as sumclose,
SUM(CASE WHEN status='NULL' then 1 ELSE 0 END) as sumunflag
from tb_r_orderdata
group by tb_r_orderdata.finishtime

MySQL: Case Query within a Case Query?

I have a query that gets unit count and it tagging if completed or not.
SELECT distinct location,
case when id is NULL then 'Not Started'
when '1' then 'Completed'
else 'In Progress' end as Remarks,
count(name) as CountName
FROM table
group by location,
case when id is NULL then 'Not Started'
when '1' then 'Completed'
else 'In Progress' end;
Result:
But I want to summarized this as below image:
Condition is when there are more that two(2) Remarks in Location it should be tagged as "In-progress" and sum the CountName. But when only one Remarks for a Location, gets the Remarks as its tagged.
Not sure on this (sample data would help), but try this:
SELECT Location,
case when count(id) > 1 then 'In Progress'
when max(id) is null then 'Not Started'
when max(id) = 1 then 'Completed'
else 'In Progress' end As Remarks,
count(name) as CountName
FROM table
GROUP BY location
Like you said, a case within a case:
select location,
case when count(distinct case when id is null then 'Not Started'
when id = '1' then 'Completed'
else 'In Progress' end) > 1
then 'In Progress'
else max(case when id is null then 'Not Started'
when id = '1' then 'Completed'
else 'In Progress' end)
end as remarks,
count(*) as CountName
from tbl
group by location
SQLFiddle Demo
Try This query:-
SELECT location,
if(count(1) > 1, 'In Progress', Remarks) Remarks,
sum(countName) countName
FROM location
group by location

mysql join the 2 tables to produce following output

I have two tables: users and user_fingerprints.
How do I combine the two tables to produce the output?
I tried
select u.id, u.name,
case f.finger (when 0 then 'y' else 'n' end) '0',
case f.finger (when 1 then 'y' else 'n' end) '1',
case f.finger (when 2 then 'y' else 'n' end) '2',
case f.finger (when 3 then 'y' else 'n' end) '3',
case f.finger (when 4 then 'y' else 'n' end) '4',
case f.finger (when 5 then 'y' else 'n' end) '5',
case f.finger (when 6 then 'y' else 'n' end) '6'
from user u left join user_fingerprint f
on u.id=f.user_id
group by u.id
but the result will only take one row from same id and update it in the output table. when i use max function, it worked, but is there any way without using max?
Use an aggregation function:
select u.id, u.name,
max(case f.finger when 0 then 'y' else 'n' end) as '0',
max(case f.finger when 1 then 'y' else 'n' end) as '1',
max(case f.finger when 2 then 'y' else 'n' end) as '2',
max(case f.finger when 3 then 'y' else 'n' end) as '3',
max(case f.finger when 4 then 'y' else 'n' end) as '4',
max(case f.finger when 5 then 'y' else 'n' end) as '5',
max(case f.finger when 6 then 'y' else 'n' end) as '6'
from user u left join
user_fingerprint f
on u.id = f.user_id
group by u.id;
I would suggest that you reconsider using integers as column aliases. Looks doomed to be confusing . . . or worse, to cause hard to spot errors.
Also, note that max() works because 'y' > 'n'. There are other methods if you don't want to depend on that.
This also assumes that you want one summary row for each column. Otherwise you might want something like group_concat().
Not sure why don't you want to use function max, without max I think you can do it like this:
SELECT
u.id, u.name,
CASE WHEN LOCATE('0', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `0`,
CASE WHEN LOCATE('1', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `1`,
CASE WHEN LOCATE('2', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `2`,
CASE WHEN LOCATE('3', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `3`,
CASE WHEN LOCATE('4', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `4`,
CASE WHEN LOCATE('5', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `5`,
CASE WHEN LOCATE('6', GROUP_CONCAT(f.finger) THEN 'y' ELSE 'n' END `6`
FROM USER u
LEFT JOIN user_fingerprint f ON u.id = f.user_id
GROUP BY u.id
GROUP_CONCAT will concat all finger for each user and separated by comma, then LOCATE will return the index of first parameter in second parameter.

Compare columns from SUM(CASE...END) in the same query

I'm trying to add a column named Ready to my query that checks if the sum of Complete is = to the sum of Total and places 'Y' if True and 'N' if FALSE.
Here is my query that works producing 4 columns
SELECT pc.Sub,
SUM(CASE WHEN `SheetStatus` LIKE 'Complete' THEN 1 ELSE 0 END) AS 'Complete',
SUM(CASE WHEN `SheetStatus` LIKE 'Not started' THEN 1 ELSE 0 END) AS 'Not Started',
SUM(CASE WHEN `CheckSheet` LIKE '%' THEN 1 ELSE 0 END) AS 'Total'
FROM `pc`
Group By pc.Sub WITH ROLLUP
I just cant figure out how to create the extra column if it is possible at all.
Regards
Try outer SELECT
SELECT `Complete`,
`Not Started`,
`Total`,
CASE WHEN `Complete` = `Total` THEN 'Y' ELSE 'N' END `Ready`
FROM (
SELECT pc.Sub,
SUM(CASE WHEN `SheetStatus` LIKE 'Complete' THEN 1 ELSE 0 END) AS `Complete`,
SUM(CASE WHEN `SheetStatus` LIKE 'Not started' THEN 1 ELSE 0 END) AS `Not Started`,
SUM(CASE WHEN `CheckSheet` LIKE '%' THEN 1 ELSE 0 END) AS `Total`
FROM `pc`
GROUP BY pc.Sub WITH ROLLUP) t
Try this:
SELECT pc.Sub,
SUM(IF(`SheetStatus`='Complete',1,0) AS 'Complete',
SUM(IF(`SheetStatus`='Not started',1,0) AS 'Not Started',
SUM(IF(`CheckSheet` LIKE '%',1,0) AS 'Total'
IF(SUM(IF(`CheckSheet` LIKE '%',1,0) = SUM(IF(`SheetStatus`='Complete',1,0),"Y","N") AS Ready
FROM `pc`
Group By pc.Sub WITH ROLLUP

Case When with AND?

I want to use Case When with AND condition and it is not calculating the sum properly.
For example:
SELECT DATE(`SubmitDate`),
SUM(CASE status WHEN 'New' AND `Type` = 'consumer' THEN 1 ELSE 0 END) as new_consumer,
SUM(CASE status WHEN 'New' AND `Type` = 'business' THEN 1 ELSE 0 END) as new_business
FROM report
WHERE `source` = 'net'
group by DATE(`SubmitDate`) Order by `SubmitDate` DESC
You need to use CASE WHEN [Condition] THEN... rather than a simple case expression:
SELECT DATE(`SubmitDate`),
SUM(CASE WHEN status = 'New' AND `Type` = 'consumer' THEN 1 ELSE 0 END) as new_consumer,
SUM(CASE WHEN status = 'New' AND `Type` = 'business' THEN 1 ELSE 0 END) as new_business
FROM report
WHERE `source` = 'net'
group by DATE(`SubmitDate`) Order by `SubmitDate` DESC
You should write
CASE WHEN status='New' AND `Type` = 'consumer' THEN 1 ELSE 0 END
Check the syntax of CASE WHEN