SQL count when value = 1 - mysql

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);

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.

MySQL Group By Query X or not X

This should be easy but I have not found the answer. I have a query that is running a count and I want to group this within the query into those where State = 1 and State <>1 and have the sum for each group.
SELECT count(`id_job`) as count, `state`
FROM job_table
GROUP BY `state`;
You can query a boolean expression and group by it too:
SELECT state = 1, COUNT(*)
FROM job_table
GROUP BY state = 1
SELECT count(id_job) as count,state FROM job_table
GROUP BY case when state = 1 then 1 else 0
In MySQL, you can easily put these into columns:
select sum( state = 1 ) as state_1,
sum( state <> 1 ) as state_2
from job_table;
If state can be NULL, you want to be a bit careful. The second condition is safer as:
select sum( state = 1 ) as state_1,
sum( not state <=> 1 ) as state_2
from job_table;
Try this
SELECT SUM(CASE WHEN State=1 THEN 1 END) as count1,
SUM(CASE WHEN State<>1 THEN 1 END) as count2,
State
FROM job_table
GROUP BY state

mysql SELECT columns but use WHERE to only one

I have this query:
SELECT i.d, COUNT(id) AS dr, COUNT(id2) AS dn, SUM(eq) AS eq_sum, COUNT(thx) AS thx_count
FROM dsd
INNER JOIN
(
SELECT COUNT(id) AS d FROM ds
) i
Now I want to use WHERE only to column thx like WHERE thx="y" , so that it will count only all values with "y".
But If I just add WHERE at the end of the query it will affect other columns as well which I don't want to.
How to do this?
Then change your COUNT(thx) AS thx_count to below using CASE expression like
COUNT(CASE WHEN thx = 'y' THEN 1 ELSE 0 END) AS thx_count
(OR)
SUM(CASE WHEN thx = 'y' THEN 1 ELSE 0 END) AS thx_count

Subquery SUM with different date

I retrieve two sum of value:
SUM (CASE WHEN CAUSALI.AVAILABLECAUSA_1 LIKE ('%CAUSE-1%') THEN (mtscrap) ELSE 0 END ) as Cause1
and
SUM (CASE WHEN CAUSALI.AVAILABLECAUSA_1 LIKE ('%CAUSE-2%') THEN (mtscrap) ELSE 0 END ) as Cause2
I would like to set another SUM statement without %CAUSE-*, and that have WHERE clause independent from the principal WHERE. I had innested this subquery:
(CASE WHEN day BETWEEN '2014-01-09' AND '2014-06-13' THEN SUM(MTSCRAP) ELSE 0 END) AS XXXXXX
but I have wrong data. My global query is:
SELECT
SezioneID
, Desc_Prod
, sample.products.VETTURA AS VetturaID
, truncate((SUM(mtscrap_1) / SUM(MtProdotti_1)) * 100, 2) AS Scrap_1
, truncate((SUM(mtscrap_2) / SUM(MtProdotti_2)) * 100, 2) AS Scrap_2
, mtscrap_1
, MtProdotti_1
, mtscrap_2
, MtProdotti_2
FROM flB.flB_prod AS PROD
JOIN SAMPLE.PRODUCTS
ON (sample.products.SKU = PROD.SEZIONEID)
AND (sample.products.LINEA = 'FLB')
JOIN (
SELECT
IDSEZIONE
, IDTURNO
, ID_PROG
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN mtscrap ELSE 0
END) AS mtscrap_1
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN MtProdotti ELSE 0
END) AS MtProdotti_1
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN mtscrap ELSE 0
END) AS mtscrap_2
, SUM(CASE
WHEN AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN MtProdotti ELSE 0
END) AS MtProdotti_2
, MtProdotti
FROM FLB.flB_causali
WHERE DATASTARTPRG BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
IDSEZIONE
IDTURNO
, ID_PROG
) AS CAUSALI
ON (PROD.SEZIONEID = CAUSALI.IDSEZIONE)
AND PROD.TURNO = CAUSALI.IDTURNO
AND PROD.ID_PROG = CAUSALI.ID_PROG
WHERE giorno BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
SezioneID
I need this view:
I have done my best to put a table or alias beside EVERY field reference. At this point I really do not know what else I can do for you. I don't think any more words will help.
these 2 simple items will help:
1. sample data
2. expected result
Because you did not use table aliases on all fields in the very original query the following is a complete guess, but using the presence of DISTINCT in that original query was a clue for "too many rows" that indicated the need for grouping prior to the overall query. So, here's my first guess:
SELECT
PROD.SezioneID
, PROD.Desc_Prod
, sample.products.VETTURA AS VetturaID
, truncate((SUM(CAUSALI.mtscrap_1) / SUM(CAUSALI.MtProdotti_1)) * 100, 2) AS Scrap_1
, truncate((SUM(CAUSALI.mtscrap_2) / SUM(CAUSALI.MtProdotti_2)) * 100, 2) AS Scrap_2
, CAUSALI.mtscrap_1
, CAUSALI.MtProdotti_1
, CAUSALI.mtscrap_2
, CAUSALI.MtProdotti_2
FROM flB.flB_prod AS PROD
JOIN SAMPLE.PRODUCTS
ON (sample.products.SKU = PROD.SEZIONEID)
AND (sample.products.LINEA = 'FLB')
JOIN (
SELECT
flB_causali.IDSEZIONE
, flB_causali.IDTURNO
, flB_causali.ID_PROG
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN flB_causali.mtscrap ELSE 0
END) AS mtscrap_1
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-1%') THEN flB_causali.MtProdotti ELSE 0
END) AS MtProdotti_1
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN flB_causali.mtscrap ELSE 0
END) AS mtscrap_2
, SUM(CASE
WHEN flB_causali.AVAILABLECAUSA_1 LIKE ('%CHANGE-2%') THEN flB_causali.MtProdotti ELSE 0
END) AS MtProdotti_2
, flB_causali.MtProdotti
FROM FLB.flB_causali
WHERE flB_causali.DATASTARTPRG BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
flB_causali.IDSEZIONE
flB_causali.IDTURNO
, flB_causali.ID_PROG
) AS CAUSALI
ON (PROD.SEZIONEID = CAUSALI.IDSEZIONE)
AND PROD.TURNO = CAUSALI.IDTURNO
AND PROD.ID_PROG = CAUSALI.ID_PROG
WHERE PROD.giorno BETWEEN '2014-06-09' AND '2014-06-13'
GROUP BY
PROD.SezioneID
;
Are you looking for this expression?
SUM(CASE WHEN day BETWEEN '2014-01-09' AND '2014-06-13' THEN MTSCRAP ELSE 0 END) AS XXXXXX
The CASE goes inside the SUM() for conditional aggregation.

get count of two table fields in one query

I am trying to get the count of females and males in the gender field of a table.
Is there a way to get the count of each in one query?
Something like:
select * from table count(where gender = 'm') as total_males, count(where gender = 'f') as total_females;
or will it require two queries?
select count(*) from table where gender = 'm';
select count(*) from table where gender = 'f';
This is basically a PIVOT. MySQL does not have a pivot so you can use an aggregate function with a CASE statement to perform this:
select
sum(case when gender = 'm' then 1 else 0 end) Total_Male,
sum(case when gender = 'f' then 1 else 0 end) Total_Female
from yourtable
See SQL Fiddle with Demo
Or using COUNT:
select
count(case when gender = 'm' then 1 else null end) Total_Male,
count(case when gender = 'f' then 1 else null end) Total_Female
from yourtable;
See SQL Fiddle with Demo
Something like this will work:
SELECT SUM(IF(t.gender='m',1,0)) AS total_males
, SUM(IF(t.gender='f',1,0)) AS total_females
FROM mytable t
The "trick" here is that we are using a conditional test to return either a 0 or a 1 for each row, and then adding up the 0's and 1's. To make this a little more clear, I am using the SUM aggregate function rather than COUNT, although COUNT could be used just as easily, though we'd need to return a NULL in place of the zero.
SELECT COUNT(IF(t.gender='m',1,NULL)) AS total_males
, COUNT(IF(t.gender='f',1,NULL)) AS total_females
FROM mytable t
Consider that the two expressions in the SELECT list of this query:
SELECT COUNT(1)
, SUM(1)
FROM mytable t
Will return the same value.
If you want to avoid the MySQL IF function, this can also be done using the ANSI SQL CASE expression:
SELECT SUM( CASE WHEN t.gender = 'm' THEN 1 ELSE 0 END )) AS total_males
, SUM( CASE WHEN t.gender = 'f' THEN 1 ELSE 0 END )) AS total_females
FROM mytable t
select sum(case when gender='m' then 1 else null end) as total_males, sum(case when gender='f' then 1 else null end) as total_females from ...
Should work just fine!
If your only issue is to avoid two queries, you can always write two queries as subselects of one query.
Select (select 1 from dual) as one, (select 2 from dual) as two from dual
This would work for your scenario, too.