How do i add SUM with multiple WHERE condition? - mysql

I am currently facing an issue with multiple WHERE condition
I am trying to do this condition.
SUM(IF SUM(B.answer) is lesser than 5),
SUM(IF SUM(B.answer) is between 6-10),
SUM(IF SUM(B.answer) is between 11-15),
SUM(IF SUM(B.answer) is greater than 16)
GROUP BY A.schlvl
Expecting a result like this:
Hope someone get the idea of my explanation
SELECT DISTINCT A.schlvl AS school, COUNT(DISTINCT(A.name)) AS NoOfChild, CASE WHEN SUM(B.answer)<5 THEN SUM(B.answer) END FROM child AS A INNER JOIN question AS B ON A.child_id = B.child_id
WHERE SUM(B.answer) IN (<5,>=6 && <=10,>=11 && <=15,>=16)
GROUP BY A.schlvl

Instead of using SUM inside a CASE WHEN, what you can do is SUM the CASE WHEN.
In this case however, when looking at the screenshot of the expected result?
I think it needs COUNT's instead.
Example:
SELECT
A.schlvl AS [School Level],
COUNT(DISTINCT(A.name)) AS [Total No. Of Children],
COUNT(DISTINCT CASE WHEN B.sum_answer <= 5 THEN A.name END) AS [le 5],
COUNT(DISTINCT CASE WHEN B.sum_answer between 6 and 10 THEN A.name END) AS [6 to 10],
COUNT(DISTINCT CASE WHEN B.sum_answer between 11 and 15 THEN A.name END) AS [11 to 15],
COUNT(DISTINCT CASE WHEN B.sum_answer >= 16 THEN A.name END) AS [ge 16]
FROM child AS A
LEFT JOIN
(
SELECT child_id, SUM(answer) AS sum_answer
FROM question
GROUP BY child_id
) AS B ON A.child_id = B.child_id
GROUP BY A.schlvl
Also, if a limit on an aggregation (f.e. SUM, COUNT) is needed, then one would do that in the HAVING clause.
I currently think it's not needed here.
Since getting the ranges of <=5 or between 6 and 15 or >=16 is hardly a limit. You need them all?

if you need a filter on aggregated result you must use having and not where
and you should use a valid or clause not a in clause with range
SELECT DISTINCT A.schlvl AS school
, COUNT(DISTINCT(A.name)) AS NoOfChild
, CASE WHEN SUM(B.answer)<5 THEN SUM(B.answer) END
FROM child AS A
INNER JOIN question AS B ON A.child_id = B.child_id
HAVING SUM(B.answer) IN (<5,>=6 && <=10,>=11 && <=15,>=16)
HAVING SUM(B.answer) < 5
OR (SUM(B.answer) >=6 AND SUM(B.answer) <=10)
OR (SUM(B.answer) >=11 AND SUM(B.answer) <=15)
OR (SUM(B.answer) >=16)
GROUP BY A.schlvl

Related

Count if avg is below/above X

I am trying to get the number of 'critics' and 'promoters' from average of ratings from a joined table on a specific group of questions
SELECT category
, SUM( IF( round(avg(items.value) ) <= 6, 1, 0) ) AS critics
, SUM( IF( round(avg(items.value) ) >= 9, 1, 0) ) AS promoters
FROM reviews
INNER JOIN items
ON reviews.id = items.review_id
AND items.question_id in (1, 2, 4)
GROUP BY category
However I get the error:
General error: 1111 Invalid use of group function
I think you should try with using having with it, something like below:
SELECT
category,
COUNT(items.id) AS critics
FROM reviews
INNER JOIN items ON reviews.id = items.review_id AND
items.question_id IN (1, 2, 4)
GROUP BY category
HAVING ROUND(AVG(items.value)) <= 6
First retrieve category wise rounded average value and then apply condition either it is critics and promoters.
-- MySQL
SELECT t.category
, CASE WHEN t.avg_value <= 6
THEN 1
ELSE 0
END critics
, CASE WHEN t.avg_value >= 9
THEN 1
ELSE 0
END promoters
FROM (SELECT category
, ROUND(AVG(items.value)) avg_value
FROM reviews
INNER JOIN items
ON reviews.id = items.review_id
AND items.question_id IN (1, 2, 4)
GROUP BY category) t
Please check this url for finding out pseudocode https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2679b2be50c3059c73ab9754c612179c
First retrieve category and review_id wise rounded average value and then apply condition either it is critics and promoters.
SELECT t.category
, SUM(CASE WHEN t.avg_value <= 6
THEN 1
ELSE 0
END) critics
, SUM(CASE WHEN t.avg_value >= 9
THEN 1
ELSE 0
END) promoters
FROM (SELECT category
, items.review_id
, ROUND(AVG(items.value)) avg_value
FROM reviews
INNER JOIN items
ON reviews.id = items.review_id
AND items.question_id IN (1, 2, 4)
GROUP BY category
, items.review_id) t
GROUP BY t.category

mysql Rollup sums to 0 on some columns

I have a Rollup query in mysql to create the weekly report and i want to sum up the numbers in the last row:
SELECT case when ISNULL(Datum) then 'Summe' ELSE Datum end AS Datum,
`Anzahl angenommen`,
`unvollständig`,
KDA,
Freigabe
FROM(
SELECT F.eindat AS Datum,
COUNT(F.eindat) AS 'Anzahl angenommen',
COUNT(T.blocker) AS 'unvollständig',
case when B.KDA IS NULL then 0 ELSE B.KDA END AS KDA,
case when P.Freigabe IS NULL then 0 ELSE P.Freigabe END AS Freigabe
FROM mukl.fall F
left JOIN mukl.ticket T ON T.fall = F.ID
LEFT JOIN (SELECT F.beadat AS Datum, COUNT(F.beadat) AS KDA
FROM mukl.fall F
WHERE F.eindat >= '2021-08-07'
GROUP BY F.beadat) B ON B.Datum = F.eindat
LEFT JOIN (SELECT F.prudat AS Datum, COUNT(F.prudat) AS Freigabe
FROM mukl.fall F
WHERE F.eindat >= '2021-08-07'
GROUP BY F.prudat) P ON P.Datum = F.eindat
WHERE F.eindat >= '2021-08-07'
GROUP BY F.eindat WITH rollup
) AS DT
Sadly the output is only partly what i want:
The first two columns are summed up correctly, the last two just display as 0, although the sum is not 0. Is there a way to fix this?
please try with this pseudocode
-- MySQL (v5.8)
SELECT CASE WHEN datum IS NULL THEN 'sum' ELSE datum END dat
, SUM(a) a, SUM(b) b
, SUM(c) c, SUM(d) d
FROM test
GROUP BY datum WITH ROLLUP;
Please check from url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=19fdd64ce99647ce751004b1580766d1
In your query use aggregate function of all columns except GROUP BY columns
SELECT F.eindat AS Datum,
COUNT(F.eindat) AS 'Anzahl angenommen',
COUNT(T.blocker) AS 'unvollständig',
SUM(case when B.KDA IS NULL then 0 ELSE B.KDA END) AS KDA,
SUM(case when P.Freigabe IS NULL then 0 ELSE P.Freigabe END) AS Freigabe

Mysql query null field replace with custom if statement

I have the below Mysql query doest quite work as expected yet. I am not a Mysql expert but basically what I am trying to do is for every AptStatus = 3 I have a Null field for Operatory. Id like to convert that Null field to the Operatory name for each count of the location. (hopefully that makes sense).
select Location, AptDate, IF(AptStatus = 3, '08:00:00', AptTime) AptTime, IF(AptStatus = 3, 540, AptLength) AptLength,AptStatus, OperatoryNum, Operatory
from rpt_officeschedules
where AptTime between '07:59:00' and '17:30:00' and AptDate between '2020-11-07' and '2020-11-08' and (Operatory LIKE '%NP%' or Operatory LIKE '%OPEN%'or Operatory is null )
order by Location, AptDate, OperatoryNum,AptTime, Operatory;
Sample Data
That location has these operators that come from the same table.
The expected results is this
Any ideas?
You seem to want a join:
select
o.location,
o.aptdate,
case when o.aptstatus = 3 then '08:00:00' else o.apttime end as apttime,
case when o.aptstatus = 3 then 540 else o.aptlength end as aptlength,
o.aptstatus,
o.operatory,
a.operatory as operatorynum
from rpt_officeschedules o
inner join apptwidget_operatorie a on a.location = o.location
where
o.apttime between '07:59:00' and '17:30:00'
and o.aptdate between '2020-11-07' and '2020-11-08'
and (o.operatory like '%np%' or o.operatory like '%open%' or o.operatory is null)
order by o.location, o.aptdate, o.operatorynum, o.apttime, o.operatory;
I think you might want to cycle through the second table assigning the values in a round-robin fashion. If so, you can use window functions:
select os.Location, os.AptDate,
(case when os.AptStatus = 3 then '08:00:00' else os.AptTime end) as AptTime,
(case when os.AptStatus = 3 then 540 else os.AptLength end) as AptLength,
os.AptStatus, os.OperatoryNum, os.Operatory
from (select os.*,
row_number() over (partition by location order by atpdate) as seqnum
from rpt_officeschedules os
where os.AptTime between '07:59:00' and '17:30:00' and
os.AptDate between '2020-11-07' and '2020-11-08' and
(Operatory LIKE '%NP%' or Operatory LIKE '%OPEN%'or Operatory is null )
) os join
(select aw.*, count(*) over (partition by location) as cnt,
row_number() over (partition by location order by location) as seqnum
from appwidget ap
) ap
on os.location = ap.location and
(os.seqnum - 1) % sp.cnt = ap.seqnum - 1
order by os.Location, os.AptDate, os.OperatoryNum, os.AptTime, os.Operatory;

Adding two columns in mysql distinguish the count of male and female

I am trying to add two new columns to my query to be able to get the count of males and females
SELECT adggeth.reg01_maininfo.techname AS TechName
,adggeth.reg01_maininfo.techmobile AS Mobile
,monthname(adggeth.lng02_rpt_b_calvedets.calvdatealv) AS "Calving Month"
,count(adggeth.lng02_rpt_b_calvedets.sex) AS "No of Calves"
FROM adggeth.reg01_maininfo
INNER JOIN adggeth.lng02_maininfo ON adggeth.reg01_maininfo.techmobile = adggeth.lng02_maininfo.aitechid
INNER JOIN adggeth.lng02_rpt_b_calvedets ON adggeth.lng02_maininfo.hh_id = adggeth.lng02_rpt_b_calvedets.hh_id
AND adggeth.lng02_maininfo.visitdate = adggeth.lng02_rpt_b_calvedets.visitdate
GROUP BY adggeth.reg01_maininfo.techname
,adggeth.reg01_maininfo.techmobile
,monthname(adggeth.lng02_rpt_b_calvedets.calvdatealv);
I need to count the number of my female and male calves where
lng02_rpt_b_calvedets.sex = 1 refers to male calves
lng02_rpt_b_calvedets.sex = 2 refers to female calves
Just found my answer
SELECT
adggeth.reg01_maininfo.techname AS TechName,
adggeth.reg01_maininfo.techmobile AS Mobile,
MONTHNAME(
adggeth.`serv00_rpt_calvdtls2`.`calvdatealv2`
) AS "Calving Month",
COUNT(
adggeth.`serv00_rpt_calvdtls2`.`sex2`
) AS "No of Calves",
COUNT(
IF (
adggeth.serv00_rpt_calvdtls2.sex2 = 2,
adggeth.serv00_rpt_calvdtls2.sex2,
NULL
)
) AS 'Femal Calf',
COUNT(
IF (
adggeth.serv00_rpt_calvdtls2.sex2 = 1,
adggeth.serv00_rpt_calvdtls2.sex2,
NULL
)
) AS 'Male Calf'
FROM
adggeth.reg01_maininfo
INNER JOIN adggeth.`serv00_maininfo`
ON adggeth.reg01_maininfo.techmobile = adggeth.`serv00_maininfo`.`aitechid`
INNER JOIN adggeth.`serv00_rpt_calvdtls2`
ON adggeth.`serv00_maininfo`.`fid` = adggeth.`serv00_rpt_calvdtls2`.`fid`
AND adggeth.`serv00_maininfo`.`regdate` = adggeth.`serv00_rpt_calvdtls2`.`calvdatealv2`
GROUP BY adggeth.reg01_maininfo.techname,
adggeth.reg01_maininfo.techmobile,
MONTHNAME(
adggeth.`serv00_rpt_calvdtls2`.`calvdatealv2`
)
You can use a count call on a case expression that filters the calves according to their sex:
COUNT (CASE adggeth.lng02_rpt_b_calvedets.sex WHEN 1 END) as "No of Male Calves",
COUNT (CASE adggeth.lng02_rpt_b_calvedets.sex WHEN 2 END) as "No of Female Calves"
You can also use COUNT aggregation with IF function:
COUNT (IF(adggeth.lng02_rpt_b_calvedets.sex = 1, 1, NULL) ) AS Male_Calves_Count,
COUNT (IF(adggeth.lng02_rpt_b_calvedets.sex = 2, 1, NULL) ) AS Female_Calves_Count,
While COUNT will not count NULLs, and therefore it is possible to use some condition which returns NULL if it's not the value you're looking for, it's much simpler to use SUM instead. Boolean expressions in MySQL return 1 or 0, so you can add up their values directly.
SELECT
SUM(adggeth.serv00_rpt_calvdtls2.sex2 = 2) AS 'Female Calf',
SUM(adggeth.serv00_rpt_calvdtls2.sex2 = 1) AS 'Male Calf'
...

COUNT multiple types of same column

In my current query:
SELECT COUNT(WC.ID) AS "Regions"
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
;
I COUNT(WC.ID) AS "Regions" .
However, we have multiple regions with WC.Type can be 1,2,3,4. I need to count each type occurrence into COUNT(WC.ID) AS "Region_1", COUNT(WC.ID) AS "Region_2" ... depending on WC.Type.
Is there any way to solve this in one query? I am looking at MySQL IF, yet do not know how to integrate it into the count function.
I need it to be in one row (the shown query here is reduced, it's a larger query)
SELECT COUNT(WC.ID) AS "Region_1" , COUNT(WC.ID) AS "Region_2" ...
Here is the complete query if anyone is interested:
SELECT PCS.PDB_id, PCS.Chain, PPA.ENSEMBL_start, PPA.ENSEMBL_end, PPA.eValue, PIN.TITLE AS "pdbTitle", COUNT(WC.ID) AS "Regions"
FROM PDB_Chains AS PCS
LEFT JOIN WHOLE_FEATURES_PDB_CHAINS AS WC ON WC.PDB_CHAIN_ID = PCS.idPDB_chains, PDB_protein_alignment PPA, PDB_INFOS PIN
WHERE PCS.idPDB_chains = PPA.idPDB_Chains
AND PCS.PDB_id = PIN.PDB_ID
AND PPA.idProteins = (SELECT idProteins from Proteins WHERE ENSEMBL_protein_id = "'+submittedID+'")
GROUP BY PCS.PDB_id, PCS.Chain ORDER BY PCS.PDB_id;
Here's the working solutin based on your kind answers
SELECT PIN.TITLE AS "pdbTitle", COUNT(CASE WHEN WC.STRUCTURAL_FEATURES_ID = 1 then 1 end) AS "PPInterface" , COUNT(CASE WHEN WC.STRUCTURAL_FEATURES_ID = 4 then 1 end) AS "flexibleRegions"
FROM PDB_Chains AS PCS LEFT JOIN WHOLE_FEATURES_PDB_CHAINS AS WC ON WC.PDB_CHAIN_ID = PCS.idPDB_chains, PDB_protein_alignment PPA, PDB_INFOS PIN
WHERE PCS.idPDB_chains = PPA.idPDB_Chains
AND PCS.PDB_id = PIN.PDB_ID
AND PPA.idProteins = (SELECT idProteins from Proteins WHERE ENSEMBL_protein_id = "ENSP00000256078.4")
GROUP BY PCS.PDB_id, PCS.Chain ORDER BY PCS.PDB_id;
You can use case when statement inside your aggregate function.
Try this .
count(case when WC.type = 1 then 1 end) as region_1, similarly repeat for another column.
Select
...
...
sum(if WC.ID = 1 then 1 else 0) as Region1,
sum(if WC.ID = 2 then 1 else 0) as Region2,
sum(if WC.ID = 3 then 1 else 0) as Region3,
sum(if WC.ID = 4 then 1 else 0) as Region4
Might do what you want.
You can use GROUP BY with COUNT to get the required result, e.g.:
SELECT WC.Type, COUNT(WC.ID) AS "Regions"
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
GROUP BY WC.Type;
Update
If you want the counts as pivoted column for each region then you can write inner SELECT queries, e.g.:
SELECT
(SELECT COUNT(ID) FROM WHOLE_FEATURES_PDB_CHAINS WHERE type = 1) AS "Region_1",
(SELECT COUNT(ID) FROM WHOLE_FEATURES_PDB_CHAINS WHERE type = 2) AS "Region_2",
other_column
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
WHERE <some condition>;