Add results of a query - mysql

I have this query:
select
sum(if(idcasa = 254, gcasa, 0)) as casa,
sum(if(idvisitante = 254, gvisitante, 0)) as visitante
from partido
where idcasa = 254 or idvisitante = 254 and idpais = 1 and idtemporada = 1 and idcategoria = 1;
and what I want is to add the results, something like this:
sum(casa + visitante) as goles

I suspect this is the query you want:
select sum(case when idcasa = 254 then gcasa else 0 end) as casa,
sum(case when idvisitante = 254 then gvisitante else 0 end) as visitante,
sum(case when idcasa = 254 then gcasa else gvisitante end) as total
from partido
where (idcasa = 254 or idvisitante = 254) and
idpais = 1 and
idtemporada = 1 and
idcategoria = 1;
First, note the change to the where clause -- the parentheses. I am guessing this is the logic your really intend.
Second, it is simple enough to just add the values in an expression. You can use a subquery to define the values first and just add them, but the expression is simple enough. And, subqueries usually incur performance overheads in MySQL.
Third, I replaced the if with case. The latter is the ANSI standard for conditional expressions.

WITH temp AS (
select
sum(if(idcasa = 254, gcasa, 0)) as casa,
sum(if(idvisitante = 254, gvisitante, 0)) as visitante
from partido
where
idcasa = 254 or idvisitante = 254
and idpais = 1
and idtemporada = 1
and idcategoria = 1
)
SELECT sum(casa + visitante) as goles FROM temp;

Related

how to convert this OR operator to case statement

i have the below query, i want to know about the case statement by changing the below type of operator.
SELECT t_product.a_productid,
t_product.a_mpactive,
t_product.a_active,
trim(substring_index(a_reference,'_',-1)) as a_reference,
t_product.a_shopid,
t_productlang.a_name,
t_deactivatedproduct.a_reason
FROM t_deactivatedproduct
inner join
(SELECT max(a_deactivatedproductid) as a_deactivatedproductid
FROM t_deactivatedproduct
GROUP by t_deactivatedproduct.a_productid) as a on a.a_deactivatedproductid = t_deactivatedproduct.a_deactivatedproductid
INNER JOIN t_product ON t_product.a_productid = t_deactivatedproduct.a_productid
INNER JOIN t_productlang ON t_product.a_productid = t_productlang.a_productid AND t_product.a_shopid IN(2,3,5,6,7,10,8,15,12,16,17,26,27,28)
WHERE t_product.a_ispublished = 1
AND ((t_product.a_active = 1 AND t_product.a_mpactive = 0)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 1)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 0))
ORDER BY t_deactivatedproduct.a_deactivatedproductid DESC limit 700;
CASE is probably not the best pick to express such boolean logic. MySQL, however, understands tuple equality, so you could rewrite this:
AND (
(t_product.a_active = 1 AND t_product.a_mpactive = 0)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 1)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 0)
)
As:
AND (t_product.a_active, t_product.a_mpactive) in ( (1, 0), (0, 1), (0, 0) )
That will make the query neater, but not necessarily faster. Under the hood, the optimizer rewrites the query and both expressions might be ultimately interpreted similarly.
If we were to phrase this with CASE, we would have to wrap it somehow, to make it look like a predicate. Something like:
AND 1 = CASE
WHEN t_product.a_active = 1 AND t_product.a_mpactive = 0 THEN 1
WHEN t_product.a_active = 0 AND t_product.a_mpactive = 1 THEN 1
WHEN t_product.a_active = 0 AND t_product.a_mpactive = 0 THEN 1
END
... And, for what it's worth... If both columns always store non-null boolean values (0/1), then the condition is simpler phrased as a negation:
WHERE NOT (t_product.a_active = 1 AND t_product.a_mpactive = 1)
Or:
WHERE (t_product.a_active, t_product.a_mpactive) not in ( (1, 1) )

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!

Return 1 or 0 in SQL depending on the multiple statements

If I find that some of the user exists with such a parameters, I want to get 1 otherwise 0. In the future I'll have to add more blocks. But it doesn't seem to work now. What am I doing wrong?
SELECT CAST(CASE WHEN EXISTS(SELECT 1
FROM Customers
WHERE Country = 'France' AND PostalCode%2 = 0)
OR (WHERE Country = 'Germany' AND PostalCode%2 = 0))
)
THEN 1
ELSE 0
END AS BIT)
You need two separate exists:
SELECT CAST(CASE WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country = 'France' AND PostalCode%2 = 0
)
THEN 1
WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country = 'Germany' AND PostalCode%2 = 0
)
THEN 1
ELSE 0
END AS BIT)
Actually, I broke this into two separate THEN clauses. This is almost equivalent to using OR, but because the logic is inside a CASE, THEN seems more natural. (The difference is that the optimizer could choose to re-arrange the OR conditions, but the THEN conditions are executed in lexical order.)
If your statements are actually this simple, you can combine them as:
SELECT CAST(CASE WHEN EXISTS (SELECT 1
FROM Customers
WHERE Country IN ('France', 'Germany') AND PostalCode%2 = 0
)
THEN 1
ELSE 0
END AS BIT)
It looks to me like you're just having issues with your bracketing:
SELECT CAST(
CASE WHEN EXISTS(
SELECT 1
FROM Customers
WHERE (Country = 'France' AND PostalCode%2 = 0)
OR (Country = 'Germany' AND PostalCode%2 = 0)
) THEN 1 ELSE 0 END AS BIT)
Building on Gordon's assumption that PostalCode%2 = 0 for all tested 'sets' of conditionals (you haven't said as much yet), you could likewise shorten this to:
SELECT CAST(
CASE WHEN EXISTS(
SELECT 1
FROM Customers
WHERE PostalCode%2 = 0
AND Country IN ('France', 'Germany')
) THEN 1 ELSE 0 END AS BIT)

how to get SUM() of COUNT() column in MySQL

i have the following query, tried using case statement
SELECT t.inst_id, t.inst_username, tcm.city_name,
SUM(CASE WHEN psb.pms_student_bucket_id IS NULL THEN 1 ELSE 0 END) AS not_assiged,
SUM(CASE WHEN COUNT(psb.pms_student_bucket_id) BETWEEN 1 AND 50 THEN 1 ELSE 0 END) AS '1-50',
SUM(CASE WHEN COUNT(psb.pms_student_bucket_id) > 50 THEN 1 ELSE 0 END) AS ' > 50'
FROM tbl_si_di t
JOIN tbl_city_master tcm ON tcm.city_id = t.city_ref_id
JOIN tbl_si_students tss ON tss.inst_ref_id = t.inst_id
LEFT JOIN pms_student_bucket psb ON psb.user_ref_id = tss.user_ref_id
GROUP BY t.inst_id;
I need SUM of pms_student_bucket_id column when their COUNT is '1-50' and '>50'. Right now this query is saying Invalid use of group function.
How would I SUM on COUNT of "pms_student_bucket_id" equals/between some value in mysql?
you could put it in a subquery
SELECT inst_id, inst_username, city_name,
SUM(pms_student_bucket_id IS NULL ) AS not_assiged,
SUM(num_bucket >=10 AND num_bucket <= 20) AS '10 - 20'
SUM(num_bucket <= 50) AS '1-50',
SUM(num_bucket > 50) AS ' > 50'
FROM
( SELECT t.inst_id, t.inst_username, tcm.city_name,psb.pms_student_bucket_id,
COUNT(psb.pms_student_bucket_id) as num_bucket
FROM tbl_si_di t
JOIN tbl_city_master tcm ON tcm.city_id = t.city_ref_id
JOIN tbl_si_students tss ON tss.inst_ref_id = t.inst_id
LEFT JOIN pms_student_bucket psb ON psb.user_ref_id = tss.user_ref_id
GROUP BY t.inst_id
)t1
GROUP BY inst_id;
note you can use the boolean values returned to do what you want.. aka you don't need a case statement, the boolean value returns a 1 or 0 which can then be summed..

SQL ORDER BY query

I want to have my table,rcarddet, ordered by "SDNO" (not primary key) in ascending order with the exception of "0". So it should turn out to be like:
1
1
2
.
.
10
0
0
My query now is:
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
AND `SDNO` != 0
ORDER BY `rcarddet`.`SDNO` ASC;
The easiest way
SELECT * FROM rcarddet
WHERE RDATE = '2011-05-25' and RCNO = '1'and PLACE = 'H'
ORDER BY CASE
WHEN rcarddet.SDNO = 0 THEN [max_number_for_the_type_of_SDNO]
ELSE rcarddet.SDNO
END ASC
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
ORDER BY
`SDNO` = 0,
`SDNO`;