group by picking columns with null value - mysql - mysql

I am working on a query and want to group the rows and return groupped data but my query is not working as expected.
my query-
select item, branch, packunit,packlevel,dealqty,PromotionFlag,PromotionID, PromotionEndDate, cnc,delivery, volumedeal, standard_price_scheme,
deliv_price_scheme
from
(
SELECT
`item` AS `item`,
`branch` AS `branch`,
`PackUnit` AS `PackUnit`,
`PackLevel` AS `PackLevel`,
`DealQty` AS `DealQty`,
`PromotionFlag` AS `PromotionFlag`,
`PromotionID` AS `PromotionID`,
`PromotionEndDate` AS `PromotionEndDate`,
SUM(`cnc`) AS `cnc`,
SUM(`delivery`) AS `delivery`,
SUM(`volumedeal`) AS `volumedeal`,
`standard_price_scheme` AS `standard_price_scheme`,
`deliv_price_scheme` AS `deliv_price_scheme`
FROM
(
SELECT DISTINCT
`Pricing_Today`.`item` AS `item`,
`Pricing_Today`.`branch` AS `branch`,
`Pricing_Today`.`price_scheme` AS `price_scheme`,
`Pricing_Today`.`PackUnit` AS `PackUnit`,
`Pricing_Today`.`PackLevel` AS `PackLevel`,
`Pricing_Today`.`DealQty` AS `DealQty`,
`Pricing_Today`.`PromotionFlag` AS `PromotionFlag`,
`Pricing_Today`.`PromotionID` AS `PromotionID`,
`Pricing_Today`.`PromotionEndDate` AS `PromotionEndDate`,
(CASE
WHEN (`Pricing_Today`.`PriceType` = 'C&C') THEN `Pricing_Today`.`Sell`
END) AS `cnc`,
(CASE
WHEN (`Pricing_Today`.`PriceType` = 'Delivery') THEN `Pricing_Today`.`Sell`
END) AS `delivery`,
(CASE
WHEN (`Pricing_Today`.`PriceType` = 'Volume Deal') THEN `Pricing_Today`.`Sell`
END) AS `volumedeal`,
(CASE
WHEN (`Pricing_Today`.`PriceType` = 'C&C') THEN `Pricing_Today`.`price_scheme`
END) AS `standard_price_scheme`,
(CASE
WHEN
((`Pricing_Today`.`PriceType` = 'Delivery')
OR (`Pricing_Today`.`PriceType` = 'Volume Deal'))
THEN
`Pricing_Today`.`price_scheme`
END) AS `deliv_price_scheme`
FROM
`Pricing_Today`
where item = 78867
and branch = 0
GROUP BY `Pricing_Today`.`item` , `Pricing_Today`.`PackUnit` , `Pricing_Today`.`PriceType`,`standard_price_scheme`,`deliv_price_scheme`
) as a
GROUP BY branch,`item` , `PackUnit`,`standard_price_scheme`,`deliv_price_scheme`
) as a
-- group by item, packunit
which returns -
BUT, when I group by item, pack I get this -
for cnc its showing null values. How do I eliminate null values and get the numbers?
Thanks in advance

You need to take aggregates of the CASE expressions:
SELECT
p.item,
p.branch,
p.price_scheme,
p.PackUnit,
p.PackLevel,
p.DealQty,
p.PromotionFlag,
p.PromotionID,
p.PromotionEndDate,
MAX(CASE WHEN p.PriceType = 'C&C' THEN p.Sell END) AS cnc,
MAX(CASE WHEN p.PriceType = 'Delivery' THEN p.Sell END) AS delivery,
MAX(CASE WHEN p.PriceType = 'Volume Deal' THEN p.Sell END) AS volumedeal,
MAX(CASE WHEN p.PriceType = 'C&C' THEN p.price_scheme END) AS standard_price_scheme,
MAX(CASE WHEN p.PriceType = 'Delivery' OR p.PriceType = 'Volume Deal'
THEN p.price_scheme END) AS deliv_price_scheme
FROM
Pricing_Today p
WHERE
item = 78867 AND branch = 0
GROUP BY
p.item,
p.branch,
p.price_scheme,
p.PackUnit,
p.PackLevel,
p.DealQty,
p.PromotionFlag,
p.PromotionID,
p.PromotionEndDate;
This is just a standard pivot query. The idea behind taking the MAX of a CASE expression is that if a given group of records has a single non NULL value, then MAX would correctly extract it. This works because MAX ignores NULL values.
Note that I removed the backticks from your query, none of which were necessary. I try to avoid using backticks unless they are really needed, because it makes the query harder to read.

Related

Can you join a table with another table you are pivoting on a field you are creating with the pivot?

I have a table I need to pivot that contains a value I need to join with a field in another table. I'm trying to determine if I can do this in one step, or if I need to pivot the first table and then join them together. GROUP_ID is in field_name in the redcap_data table and needs to be joined with group_id in redcap_data_access_groups.
CREATE VIEW vwGlobalHealthInfants AS
SELECT rd.record as record_id,
MAX(CASE WHEN rd.field_name = '__GROUP_ID__' THEN rd.value ELSE NULL END) as GroupId,
g.group_name as hospno,
MAX(CASE WHEN rd.field_name = 'admission_temperature' THEN rd.value ELSE NULL END) as adtemp,
MAX(CASE WHEN rd.field_name = 'antenatal_care' THEN rd.value ELSE NULL END) as antecare,
MAX(CASE WHEN rd.field_name = 'anti_hypertensive' THEN rd.value ELSE NULL END) as antihyper,
MAX(CASE WHEN rd.field_name = 'anticonvulsants' THEN rd.value ELSE NULL END) as anticonvul
FROM (
redcapVON.redcap_data rd
JOIN redcapVON.redcap_data_access_groups g ON ( (
GroupId = g.group_id
) )
)
WHERE (
rd.project_id = 12
)
GROUP BY rd.record
I don't know if it's possible to get it to recognize the GroupID field in the join before the pivot.
CTE would solve it. We just don't have the most updated version of mysql to run it. 2 steps it is.

Select sum with a group by inside a group by

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

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

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.

MySQL PIVOT and JOIN inner MAX CASE

I have two tables domain and domain_meta. What I want to accomplish is to PIVOT table domain_meta (which Im able to do) and join that table with domain. But I cant wrap my head arround how to join this tables with a PIVOT and MAX CASE. Is the simplest way to use some sort of inner select to my domain_meta table? My code looks like this so far:
domain
SELECT
*
FROM
domain
ORDER BY id
domain_meta
SELECT
id,
domain_id,
source,
MAX(CASE WHEN (meta_key = 'domain') THEN meta_value ELSE NULL END) AS domain,
MAX(CASE WHEN (meta_key = 'ip') THEN meta_value ELSE NULL END) AS ip,
MAX(CASE WHEN (meta_key = 'link') THEN meta_value ELSE NULL END) AS link,
MAX(CASE WHEN (meta_key = 'net') THEN meta_value ELSE NULL END) AS net
FROM
domain_meta
GROUP BY id
ORDER BY id
domain
domain_meta
Something like this -
SELECT
d.id,
d.domain,
MAX(CASE WHEN (dm.meta_key = 'domain') THEN dm.meta_value ELSE NULL END) AS domain,
MAX(CASE WHEN (dm.meta_key = 'ip') THEN dm.meta_value ELSE NULL END) AS ip,
MAX(CASE WHEN (dm.meta_key = 'link') THEN dm.meta_value ELSE NULL END) AS link,
MAX(CASE WHEN (dm.meta_key = 'net') THEN dm.meta_value ELSE NULL END) AS net
FROM
domain d
LEFT JOIN domain_meta dm
ON d.id = dm.domain_id
GROUP BY d.id