Diffrence between sum of two products > 0 - mysql

I want to select the sum of T_No where Transactions are equal to R and subtract it by T_No where Transactions are equal to D and the answer of this should greater than zero for a CustomerID which would be a input (an int input declared in a stored procedure)
((Sum(T_No) where Transactions = R - Sum(T_No) where Transactions = D ) > 0) where CoustomerID = #input
Example : for ID = 1 it would be ((20+15) - 10) > 0
I Have tried so many things but either syntax is wrong, wrong value or it does not accept, and I am literally Stuck, this was my final attempt
SELECT
(select ( select Sum(T_No) where Transactions = R) - (select Sum(T_No) where Transactions = D) as C_T )
FROM CustomerTrans WHERE C_T > 0 ;

Conditional aggregation should help:
SELECT
SUM(CASE WHEN Transaction = 'R' THEN t_no ELSE 0 END) - SUM(CASE WHEN Transaction = 'D' THEN t_no ELSE 0 END)
FROM CustomerTrans
WHERE CoustomerID = #yourCustomerIdVariable
As you're writing a sproc you can assign the result of this to a variable and then decide what to do if the result is negative. (I would personally log an error for example, rather than just hide those results). If the result is null, then there were no transactions for that customer
ps; I used Transaction because that's what your screenshot showed, and I figured a screenshot is less likely to contain a typo than code with syntax errors. Adjust if required

you where kinda close, I would sum like you, only the syntax is a bit off, you can't have aggregate fields in Where, thats why you should use having, also case when syntax is not correct.
Select
CoustomerID,
Sum(case when Transactions = 'R' then T_No else 0 end) -
Sum(case when Transactions = 'D' then T_No else 0 end) as C_T
FROM CustomerTrans
group by CoustomerID
having (Sum(case when Transactions = 'R' then T_No else 0 end) -
Sum(case when Transactions = 'D' then T_No else 0 end))>0

Related

Integrate calculated AVG into same query

I have some troubles and hope you will help me. I need to calculate how many contracts there are in which hcb.sum:
<= 10k
greater than 10k but < AVG
greater than AVG
In the first case, everything is simple, but the problem arises when I need to count the following two cases: "> 10 but < AVG" and "> AVG". I can't solve this problem. How to integrate the calculated AVG into this query. Hope you understand what i need. Perhaps you can help me. Thanks in advance. Select is below:
SELECT hcb.id AS 'ID'
,hcb.name AS 'Name'
,SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ <= 10000 THEN 1 ELSE 0 END) AS '<= 10k'
,SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ BETWEEN 10000.01 AND **AVG** THEN 1 ELSE 0 END) AS '> 10k < AVG'
,SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ > **AVG** THEN 1 ELSE 0 END) AS '> AVG'
,AVG(hcb.summ) AS 'AVG summ'
FROM DBO AS hcb
WHERE hcb.stat IN (15, 20)
AND hcb.optstat <> 2999
AND hcb.opt = 'CI'
GROUP BY hcb.id, hcb.name
Use window functions. Presumably, you want the average with the where conditions, so:
SELECT hcb.id AS id,
hcb.name AS Name,
SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ <= 10000
THEN 1 ELSE 0
END) AS "<= 10k",
SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ > 10000 AND hcb.summ <= hcb.avg_summ
THEN 1 ELSE 0
END) AS "> 10k < AVG",
SUM(CASE WHEN hcb.kind = 'NEW' AND hcb.opt = 'CI' AND hcb.summ > hcb.avg_summ
THEN 1 ELSE 0
END) AS "> AVG",
avg_summ
FROM (SELECT hcb.*,
AVG(summ) OVER () as avg_summ
FROM DBO AS hcb
WHERE hcb.stat IN (15, 20) AND
hcb.optstat <> 2999 AND
hcb.opt = 'CI'
) hcb
GROUP BY hcb.id, hcb.name, avg_summ;
Note other changes to the query:
The column aliases are defined using double quotes not single quotes. Only use single quotes for string and date constants -- otherwise, you will one day have a confusion where you refer to a column using single quotes.
The second between is removed, replaced with >, so values between 10000 and 10000.01 are included.
If you want the overall average not subject to the filtering conditions, then move the WHERE conditions to the outer query.
I have used 3 different joins and then in SELECT statement brought up 3 different values trough something like COALESCE(MAX(d.[<10k]),0) AS '<10k'
LEFT JOIN (
SELECT r.id AS 'ID'
,COUNT(r.name) AS '<10k'
FROM DBO as r
WHERE r.stat IN (15, 20)
AND r.optstat <> 2999
AND r.opt = 'CI'
AND r.kind = 'NEW'
AND r.summ BETWEEN 10000 AND (SELECT AVG(ci.summ)
FROM DBO as ci
WHERE ci.stat IN (15, 20)
AND ci.optstat <> 2999
AND ci.opt = 'CI'
AND ci.kind = 'NEW')
GROUP BY r.id) AS d ON a.id = d.ID
Maybe it's not a best way to solve a problem, but it works for me. Thax a lot for some suggestions, they helped me. Cheers!

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.

Not able to alias column name in nested case using sql query

In this code its able to alias each case statement separately like,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN' AND a.salary = 20000)
THEN '1'
ELSE '0'
END) AS '20K Salary',
SUM(CASE
WHEN (a.place = 'CHN' and a.salary = 35000)
THEN '1'
ELSE '0'
END) AS '35K Salary'
FROM Employee a;
but when nested CASE statement is used,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN')
THEN (CASE
WHEN a.salary = 20000
THEN '1'
ELSE '0'
END) AS '20K Salary',
(CASE
WHEN a.salary = 35000
THEN '1'
ELSE '0'
END) AS '35K Salary'
END)
FROM Employee a;
its not possible to execute the query
In the first set of code each case statement is part of the SELECT list (i.e. they are in a comma separated list following SELECT) so each returns a column. In the second set of code there is only one case statement in the SELECT list, the fact that it is nested has no impact on this. Also the syntax for the nested case isn't correct because the THEN part is followed by two expressions separated by commas which is not allowed.
Of course this is possible to do what you want. You want to create two columns, so each needs its own logic and its own alias:
SELECT id,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 20000 THEN 1 ELSE 0
END) as Salary_20K,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 35000 THEN 1 ELSE 0
END) as Salary_35K
FROM Employee a;
Note: Don't put numeric constants in single quotes. Only use single quotes for string and date constants.

How do I calculate the difference of two alias for sorting

Considering the following code:
SELECT SUM(w.valor),
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit,
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit,
w.clientUNIQUE,
c.client as cclient
FROM wallet AS w
LEFT JOIN clients AS c ON w.clientUNIQUE = c.clientUNIQUE
WHERE w.status='V'
GROUP BY w.clientUNIQUE
ORDER BY total_credit-total_debit
I'm trying to calculate the difference of two aliased calculated values for sorting purposes, but I'm getting the following error:
Reference 'total_credit' not supported (reference to group function)
What am I doing wrong and how can I order results by using the difference value between the two aliases?
You can't refer to columns by their alias in the same select expression, so there are 2 options...
Repeat the expressions in the order by (yuk):
ORDER BY
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit -
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit
Or easier on the brain and easier to maintain (DRY), order via a sub query:
select * from (
<your query without the ORDER BY>
) q
ORDER BY total_credit - total_debit

MySQL sum on condition does not work in a view

In MySQL (v5.5), the value of numNotCast, numInFavor is always 0 when selecting all rows of the view. If the select statement is executed alone (not in the view), it works as expected returning the correct count of the the number of rows in the vote column equal to value 'notcast' and 'infavor'.
CREATE OR REPLACE
VIEW `Stats` AS
select
sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`,
sum(case when `p`.`vote` = 'infavor' then 1 else 0 end) AS `numInFavor`
from
(`Debate` `d`
join `Participant` `p` ON ((`d`.`debateId` = `p`.`debateId`)))
group by `d`.`debateId`
Is this a limitation on MySQL views? How do you accomplish this conditional summing function in the view?
Then your statement is correct as SQLFiddle confirms, so your problem is probably somewhere else
CREATE OR REPLACE VIEW Stats AS
select
Debate.debateId,
sum(case when Participant.vote='notcast' then 1 else 0 end) as numNotCast,
sum(case when Participant.vote='infavor' then 1 else 0 end) as numInFavor
from
Debate
inner join
Participant on Participant.debateId = Debate.debateId
group by
Debate.debateId
Updated after the clarification
There are many limitations in MySQL views, but I don't think this is one of them.
I think it is strange that the name of the view is in single quotes. That might be allowed, but the view may not be doing what you want. Try this:
CREATE OR REPLACE VIEW `Stats` AS
select sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`
from `Debate` `d` join
`Participant` `p`
ON `d`.`debateId` = `p`.`debateId`
group by `d`.`debateId`;
By the way, in MySQL, you can simplify the select to:
select sum(p.vote = 'notcast') as numNotCast