MySQL CASE , SUM, GROUP BY - mysql

I want sum of payment status from two differnt columns based on paymentstatus value - but this query returns null for sum. Why is it not working?
select payment_status,
CASE
WHEN 'PAID' THEN sum(paid_amount)
when 'Not Paid' then sum(total_amount_due )
END
from monthly_fee
group by payment_status;

select sum(CASE WHEN payment_status = 'PAID' THEN paid_amount else 0 end) as paid,
sum(CASE WHEN payment_status = 'Not Paid' THEN total_amount_due else 0 end) as due
from monthly_fee

If you want this conditionally, you need to include the column in the case:
select payment_status,
(case payment_status
when 'Paid' then sum(paid_amount)
when 'Not Paid' then sum(total_amount_due )
end)
from monthly_fee
group by payment_status;
This seems like a strange way to write the query, unless you really want two rows.

Your WHEN clauses aren't a condition.
I'd expect to see something like
select payment_status,
CASE
WHEN payment_status = 'PAID' THEN sum(paid_amount)
when payment_status = 'Not Paid' then sum(total_amount_due )
END
from monthly_fee
group by payment_status;

You can try the following query:
select sum(if(payment_status = 'PAID', paid_amount, 0)
+ if(payment_status = 'Not Paid', total_amount_due, 0))
from monthly_fee
group by payment_status;

Related

MySQL : using sum in( case when ) statement shows 0 as result

new to MySQL..so pls help me out with this basic code..
i have a query something like this...
select weekofyear(id_time),
(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
and it gives correct results as--here
however i want to use sum after case when statement so that I can get total values where BO=1 and group by week of year , so i made following changes-
select weekofyear(id_time),
count(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
sum(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
group by weekofyear(id_time)
but it always returns 0 as output.
Output --here 2
Please help , I don't know what am I doing wrong here.
Thanx !
As others have already said, session variables can be unpredictable (especially when aggregation gets mixed in). That said, it doesn't look like you're using the session variables to carry over values from one row to the next (as is often done), but to just make aliases of sorts for calculations you don't want to repeat.
A better way to handle that is just through subqueries.
SELECT woy, id, Tat1, Tat2, check1, check2
, CASE
WHEN check2=0 THEN (
CASE
WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+10))) THEN 1
ELSE 0
END
)
ELSE (
CASE WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+20))) THEN 1
ELSE 0
END
)
END AS BO
FROM (
SELECT WEEKOFYEAR(id_time) AS woy
, id
, exp1 AS Tat1
, exp2 AS Tat2
, exp3 AS check1
, exp4 AS check2
FROM datb
WHERE cid=18
AND id_time BETWEEN '2019-11-01 06:00:00' AND '2019-11-25 06:00:00'
) AS subQ
;
You can then tweak the above query for aggregation, or use it as a subquery for an aggregating outer query.

SQL count when value = 1

I'm doing a select on two tables with this:
SELECT m.torneio, m.deck, m.top, m.lugar, sum( m.quantidade ) AS quantidade, m.formato AS formato, q.quantidade AS qtorneio, t.season AS season, sum( m.top ) AS totaltops, count( m.lugar = '1' ) AS venceu
FROM `metagame` AS m, quantidade AS q, torneios AS t
WHERE m.torneio = t.nome
AND m.torneio = q.nome
GROUP BY m.deck
My problem is that venceu is counting all instances instead of only the ones when lugar = 1. Why is that?
tried with sum() too with no good results too. How can i fix this?
I am surprised that count( m.lugar = '1' ) syntaxs but it does and returns the sames as count(*). You should probably change it to sum(case when lugar = 1 else 0 end) as venceu. You should also look closely at the group by to be sure it works as you expect (i suspect not).
count(x) does not accept an expression.
It's only counting how many times x is returned.
What you should do is check if m.lugar is 1 and yes add one to the counter else do nothing.
Inline checks can be done like so:
case when m.lugar = '1' then 1 else 0 end
Then add all the one you gets :
sum(case when m.lugar = '1' then 1 else 0 end)
Your final query should look like this:
SELECT
m.torneio,
m.deck,
m.top,
m.lugar,
sum( m.quantidade ) AS quantidade,
m.formato AS formato,
q.quantidade AS qtorneio,
t.season AS season,
sum( m.top ) AS totaltops,
sum(case when m.lugar = '1' then 1 else 0 end) AS venceu
FROM
`metagame` AS m,
quantidade AS q,
torneios AS t
WHERE
m.torneio = t.nome
AND m.torneio = q.nome
GROUP BY
m.deck
If I understand your question you can use this:
sum(case when m.lugar = '1' then 1 else 0 end)
or you can try having clause
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);

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

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 Statement in SQL WHERE clause

I'm trying to fetch data from table where I'm using a CASE condition in the WHERE clause and currently I'm using following query:-
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)
AND CASE WHEN (
STATUS = 'Sold'
)
THEN delivery_date >= '2012-08-01'
END
But it returns 0 for total and NULL for purchase.
From your comment.
I want to use Case Statement, could u pls clarify me about case statament in where clause
You can use CASE statement in WHERE like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND ( STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref')
AND CASE STATUS
WHEN 'Sold'
THEN delivery_date >= '2012-08-01'
ELSE 1=1
END
Here you need to use ELSE 1=1. otherwise you will not get desired result. For more explanation see this SQLFiddle
I don't think that CASE can work that way. What you want is a slightly more complex expression as your WHERE clause. Probably something like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
(STATUS = 'Sold' AND delivery_date >= '2012-08-01')
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)