Select sum with a group by inside a group by - mysql

With this example iformation table:
How can i output this information?
I'm trying this query,
but it's just returning me the total number of 'PART' rows for each 'NAMES'.
SELECT
NAMES
, SUM(PART = "F001") AS SUM_F001
, SUM(PART = "F002") AS SUM_F002
, SUM(PART = "F003") AS SUM_F003
FROM
MY_TABLE
GROUP BY NAMES ASC

You are pretty close with your current query.
But you need to use the query below to correctly pivot.
SELECT
NAMES
, MAX(CASE WHEN PART = 'F001' THEN QTY ELSE 0 END) AS F001
, MAX(CASE WHEN PART = 'F002' THEN QTY ELSE 0 END) AS F002
, MAX(CASE WHEN PART = 'F003' THEN QTY ELSE 0 END) AS F003
, SUM(QTY) AS alias
FROM
FROM
MY_TABLE
GROUP BY
NAMES # Don't use ASC OR DESC on GROUP BY because it's deprecated
ORDER BY
NAMES ASC

U can use the query as follows
SELECT NAMES , SUM(CASE WHEN PART = 'F001' THEN 1 ELSE 0 END) AS F001 , SUM(CASE WHEN PART = 'F002' THEN 1 ELSE 0 END) AS F002 , SUM(CASE WHEN PART = 'F003' THEN 1 ELSE 0 END) AS F003 , SUM(QTY) AS alias FROM FROM MY_TABLE GROUP BY NAMES ORDER BY NAMES ASC

Related

Count different values in a column, while doing total and group by different column values

We have a table with data from different nodes and one of the column will have status report as "compliant or non-compliant", sample data as below
I want to filter the table in such a way that if any of the checks on a node shows non compliant, it should be flagged as non-compliant and rest as compliant. Using below query i am able to do it
SELECT COUNT(*) AS total_nodes,
SUM(fully_compliant = 0) AS Non_compliant_nodes,
SUM(fully_compliant = 1) AS compliant_nodes
FROM (
SELECT Node, CASE WHEN SUM(Status = 'Compliant') = COUNT(*) THEN 1 ELSE 0 END AS fully_compliant
FROM your_table GROUP BY Node
)
Now, i want to group and split the result by dept as below, how can i achieve this
I think you're looking for this:
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
sum(case when 'Non-Compliant' then 1 else 0 end) as non_compliant_chk
from your_table
group by dept,
node
) v
group by dept;
With few modifications to what Brian suggested, I am able to get the desired result
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
COUNT(CASE WHEN Compliance-Status = 'Non-Compliant' THEN 1 END) 'non_compliant_chk'
from table WHERE DOR >= DATE(NOW()) - INTERVAL 7 DAY
group by Dept,
Node
) v
group by Dept;

i want MySQL query result in same row

SELECT sum(case when (gender)=1 THEN 1 ELSE 0 END),
GROUP_CONCAT(sum(case when (gender)=2 THEN 1 ELSE 0 END) SEPARATOR ' ') as combine
from family_member_tbl
GROUP BY gender
NO, you can't nest grouping function like that. Rather get the sum first and then group_concat() like
select sum_1, sum_2, group_concat(sum_2) as combine
from (
SELECT gender,
sum(case when gender = 1 THEN 1 ELSE 0 END) as sum_1,
sum(case when gender = 2 THEN 1 ELSE 0 END) as sum_2
from family_member_tbl
GROUP BY gender ) xxx
group by gender;

How get TOP from query? [duplicate]

This question already has answers here:
Is there an alternative to TOP in MySQL?
(4 answers)
Closed 6 years ago.
SELECT
user_id,
count(*) total,
sum(case when type = 'yes' then 1 else 0 end) as type_1,
sum(case when type = 'no' then 1 else 0 end) as type_2
FROM history
GROUP by user_id
How get TOP 100 rows from this query which have max count type = 'yes' ?
You can use LIMIT to limit the number of results and use an ORDER BY to order it so the results are in descending order of total.
SELECT
user_id,
count(*) total,
sum(case when type = 'yes' then 1 else 0 end) as type_1,
sum(case when type = 'no' then 1 else 0 end) as type_2
FROM history
GROUP by user_id
ORDER BY type_1 DESC
LIMIT 100
You should add WHERE statement to your query to add conditional statement
Also, I can see that you are using mysql, so that means you should order your data by argument descending and limit result to 100
SELECT
user_id,
count(*) total,
sum(case when type = 'yes' then 1 else 0 end) as type_1,
sum(case when type = 'no' then 1 else 0 end) as type_2
FROM history
WHERE type='yes'
GROUP by user_id
ORDER BY total DESC
LIMIT 100
SELECT
user_id,
count(*) total,
sum(case when type = 'yes' then 1 else 0 end) as type_1,
sum(case when type = 'no' then 1 else 0 end) as type_2
FROM history
GROUP by user_id
ORDER by type_1 DESC
LIMIT 100

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.

SQL using CASE in count and group by

I'm using CASE to categorize data in the table and count them but the results aren't accurate
live demo [here]
select DATE(date) as day, count(*),
count(distinct case when name = 'fruit' then 1 else 0 end) as fruits,
count(distinct case when name = 'vege' then 1 else 0 end) as vege,
count(distinct case when name = 'sweets' then 1 else 0 end) as sweets
from food
group by day
with rollup
I'm not sure if the issue is with CASE or in the string matching = because there's no 'sweets' still it counts 1?
any pointers I'd be grateful
Your problem is that COUNT counts every result that is not NULL. In your case you are using:
COUNT(distinct case when name = 'sweets' then 1 else 0 end)
So, when the name is not sweets, it counts the 0. Furthermore, since you are using DISTINCT, it counts just one or two values. You should either use SUM or remove the DISTINCT and the ELSE 0:
SELECT DATE(date) as day,
COUNT(*),
SUM(CASE WHEN name = 'fruit' THEN 1 ELSE 0 END) as fruits,
SUM(CASE WHEN name = 'vege' THEN 1 ELSE 0 END) as vege,
SUM(CASE WHEN name = 'sweets' THEN 1 ELSE 0 END) as sweets
FROM food
GROUP BY DAY
WITH ROLLUP
Or:
SELECT DATE(date) as day,
COUNT(*),
COUNT(CASE WHEN name = 'fruit' THEN 1 ELSE NULL END) as fruits,
COUNT(CASE WHEN name = 'vege' THEN 1 ELSE NULL END) as vege,
COUNT(CASE WHEN name = 'sweets' THEN 1 ELSE NULL END) as sweets
FROM food
GROUP BY DAY
WITH ROLLUP
Here is a modified sqlfiddle.
You can't group by an alias. You have to group by the expression.
group by date(date)
You can group on an Alias:
SELECT
FROM_UNIXTIME(UnixTimeField, '%Y') AS 'Year'
,FROM_UNIXTIME(UnixTimeField, '%m') AS 'Month'
FROM table p
GROUP BY Year, Month