Distinct Count Query - mysql

I have a table below:
Item Status1 Status2
-----------------------------
A Good NULL
A Good NULL
A Good NULL
A Bad Good
B Bad Good
B Good NULL
C Good NULL
C Good NULL
C Good NULL
D Bad Good
Now, I'm thinking off writing a query which gives me the result below:
Item Good Bad
-----------------------------
A 4 1
B 2 1
C 3 0
D 1 1
Distinct in the Item column and the count of Good and Bad for each Item where NULL is not counted.
The column name can be of anything (I just kept it as Good and Bad in my second table).
Any suggestions/ideas on how to achieve my desired results?

Use UNION ALL & do aggregation :
select item, sum(status = 'good'), sum(status = 'bad')
from (select item, status1 as status
from table t
union all
select item, status2
from table t
) t
group by item;

You can use union all and conditional aggregation
select item, count(case when status1='good' then 1 end) as good,
count(case when status1='bad' then 1 end) as bad
from
(
select item , status1 from tablename
union all
select item , status2 from tablename
)A group by item

use union and case when
select Item, sum(case when status = 'good' then 1 else 0 end) as good,
sum ( case when status = 'bad' then 1 else 0 end) as bad
from (select Item, Status1 as status
from table_name
union all
select Item, Status2
from table_name
) t
group by Item;

There's no need for UNION, simply apply some logic.
select Item
,sum(case when Status1 = 'Good' then 1 else 0 end +
case when Status2 = 'Good' then 1 else 0 end) as good
,sum(case when Status1 = 'Bad' then 1 else 0 end +
case when Status2 = 'Bad' then 1 else 0 end) as bad
from tab
group by Item
or
select Item
,count(case when Status1 = 'Good' then 1 end) +
count(case when Status2 = 'Good' then 1 end) as good
,count(case when Status1 = 'Bad' then 1 end) +
count(case when Status2 = 'Bad' then 1 end) as good
from tab
group by Item

You can use sub-query and then apply sum function in outer query
select distinct(item) as item, sum(S1G+S2G) as Good,sum(S1B+S2B) as Bad from ( select item, CASE WHEN status1 ='Good' THEN 1 ELSE 0 END as S1G, CASE WHEN status2 ='Good' THEN 1 ELSE 0 END as S2G, CASE WHEN status2 ='Bad' THEN 1 ELSE 0 END as S2B, CASE WHEN status1 ='Bad' THEN 1 ELSE 0 END as S1B from t1 ) as b group by item
Here is demo

Related

How to use select value in next or another select value MySQL?

I want to use tahun in first select distinct value in AND tahun like ? like foreach in programming language
my code is like this
select distinct SUBSTRING_INDEX(tahun,'/', -1) as tahun,
COUNT(CASE WHEN choice = "A" AND tahun like '%2008%' THEN 1 ELSE NULL END) AS A,
COUNT(CASE WHEN choice = "B" AND tahun like '%2008%' THEN 1 ELSE NULL END) AS B,
COUNT(CASE WHEN choice = "C" AND tahun like '%2008%' THEN 1 ELSE NULL END) AS C
FROM tes;
Sorry if my english is bad,
Thank you in advance for your answer
distint tahun values
You have to GROUP the records instead of put DISTINCT
SELECT SUBSTRING_INDEX(tahun,'/', -1) as tahun,
SUM(CASE WHEN choice = 'A' THEN 1 ELSE 0 END) AS A,
SUM(CASE WHEN choice = 'B' THEN 1 ELSE 0 END) AS B,
SUM(CASE WHEN choice = 'C' THEN 1 ELSE 0 END) AS C
FROM tes
GROUP BY SUBSTRING_INDEX(tahun,'/', -1)
ORDER BY 1;

How can I simplify this mysql query, based on 2 tables?

after 2 days of trial and error, I just completed this mysql query. It works fine, but it does look really hideous. Is it possible to simplify my query ? All help is of course greatly appreciated.
SELECT
p.*,
COUNT(oT.Ontmoeting_ID) + COUNT(oU.Ontmoeting_ID) AS 'played',
COUNT(case oT.Ontmoeting_Uitploeg_FF when 1 then 1 else case oT.Ontmoeting_Thuisploeg_Bonus when 3 then 1 else null end end)
+ COUNT(case oU.Ontmoeting_Thuisploeg_FF when 1 then 1 else case oU.Ontmoeting_Uitploeg_Bonus when 3 then 1 else null end end)
- COUNT(case oU.Ontmoeting_Thuisploeg_FF when 1 then case oU.Ontmoeting_Uitploeg_FF when 1 then 1 else null end end)
- COUNT(case oT.Ontmoeting_Uitploeg_FF when 1 then case oT.Ontmoeting_Thuisploeg_FF when 1 then 1 else null end end) AS 'won',
COUNT(case oT.Ontmoeting_Thuisploeg_Bonus when 1 then 1 else null end) +
COUNT(case oU.Ontmoeting_Uitploeg_Bonus when 1 then 1 else null end) AS 'draw',
COUNT(case oU.Ontmoeting_Uitploeg_FF when 1 then 1 else case oU.Ontmoeting_Uitploeg_Bonus when 0 then 1 else null end end)
+ COUNT(case oT.Ontmoeting_Thuisploeg_FF when 1 then 1 else case oT.Ontmoeting_Thuisploeg_Bonus when 0 then 1 else null end end) AS 'lost',
SUM(COALESCE(oT.Ontmoeting_Thuisploeg_Totaal, 0)) + SUM(COALESCE(oU.Ontmoeting_Uitploeg_Totaal, 0)) AS 'Totaal'
FROM ploegen AS p
LEFT OUTER JOIN ontmoetingen AS oT ON oT.Ontmoeting_Thuisploeg_ID = p.Ploeg_ID AND oT.Ontmoeting_Competitie_ID = 1 and oT.Ontmoeting_Speelweek <= 2 AND (oT.Ontmoeting_Thuisploeg_Totaal > 0 OR oT.Ontmoeting_Thuisploeg_FF = 1)
LEFT OUTER JOIN ontmoetingen AS oU ON oU.Ontmoeting_Uitploeg_ID = p.Ploeg_ID and oU.Ontmoeting_Competitie_ID = 1 AND oU.Ontmoeting_Speelweek <= 2 AND (oU.Ontmoeting_Uitploeg_Totaal > 0 OR oU.Ontmoeting_Uitploeg_FF = 1)WHERE p.Ploeg_ID IN (select Ontmoeting_Thuisploeg_ID from ontmoetingen WHERE Ontmoeting_Competitie_ID = 1)
GROUP BY p.Ploeg_ID
ORDER BY totaal DESC
The query is based on 2 tables, "ontmoetingen" and "ploegen" (in English: "encounters" and "teams"). It calculates the overall standings of the teams, adding all played, won and draw encounters. The main difficulty is that all teams play both home and away games and those have to be summarized ("Thuisploeg" = "Home Team", "Uitploeg" = "Away Team". Please let me know if more info on the tables is required to help me out. Thx !
Table: "Ontmoetingen":
Table: "ploegen":
Expected output:
All numbers in output are fictional, so not corresponding to table data. Hope this helps !

how to get column count

i have a query like below
select project_task_id,
status_id,
sum(case when StatusID=1 then 1 else 0 end) as task_id=1,
sum(case whenStatusID=2 then 1 else 0 end) as task_id=2,
sum(case when StatusID=3 then 1 else 0 end) as task_id=3,
sum(case when StatusID=4 then 1 else 0 end) as task_id=4,
sum(case when StatusID=5 then 1 else 0 end) as task_id=5,
sum(case when StatusID=6 then 1 else 0 end) as task_id=6,
sum(case when StatusID=7 then 1 else 0 end) as task_id=7,
from"Projects".work_unit_status
group by project_task_id,status_id;
I'm getting the below attached output:
https://i.stack.imgur.com/1wfD1.png
and I want to get the below expected output:
https://i.stack.imgur.com/Zql9z.png
include zero's if the status_id is blank
please any one help on this
Try this: use the addition of all sum column
select project_task_id,status_id,
isnull(sum(case when StatusID=1 then 1 else 0 end),0)+
isnull(sum(case whenStatusID=2 then 1 else 0 end),0) +
isnullsum(case when StatusID=3 then 1 else 0 end),0) +
isnullsum(case when StatusID=4 then 1 else 0 end),0)+
isnullsum(case when StatusID=5 then 1 else 0 end),0) +
isnullsum(case when StatusID=6 then 1 else 0 end),0) +
isnullsum(case when StatusID=7 then 1 else 0 end),0) as count_status
from"Projects".work_unit_status group by project_task_id,status_id
use in with your case
with t1 as (
select project_task_id,
status_id,
sum(case when StatusID in (1,2,3,4,5,6,7) then 1 else 0)
as sum_s
from "Projects".work_unit_status
group by project_task_id,status_id
) ,
t2 as
(
select * from (
select 1 as statusid
union
select 2
union
select 3
union
select 4
union
select 5
union
select 6
union
select 7 ) t
) select t1.project_task_id,
t2.statusid,
case when t1.sum_s>0 or not null
then sum_s else 0 end as total
t2 full join t1 on t2.statusid=t1.status_id
Without knowing the exact table structure I assumed that status_id and statusId refer to the same column. (If they are different columns, we need to use StatusId in the COUNT.)
Based on the expected output, you want to count the status_id and group by project_task_id. To make sure that every status is represented for every task, first, we need to create a subquery of all possible project_task_id/status_id combinations. Then we use that with the aggregate values of the original table.
select
ps.project_task_id,
ps.status_id,
count(w.status_id) as total
from (
select distinct
project_task_id,
s.status_id
from work_unit_status
cross join (select distinct status_id from work_unit_status) s
) ps
left join work_unit_status w
on ps.project_task_id = w.project_task_id and ps.status_id = w.status_id
group by
ps.project_task_id,
ps.status_id
If you really need to hardcode the statuses from 1 to 7, use the query below.
select
ps.project_task_id,
ps.status_id,
count(w.status_id) as total
from (
select distinct
project_task_id,
s.status_id
from work_unit_status
cross join (
select 1 as status_id
union select 2
union select 3
union select 4
union select 5
union select 6
union select 7
) s
) ps
left join work_unit_status w
on ps.project_task_id = w.project_task_id and ps.status_id = w.status_id
group by
ps.project_task_id,
ps.status_id
order by
ps.project_task_id,
ps.status_id

query count id where 2 records condition

I have a problem to display some information from my table
Table
I want to count idxdaftar where this have kode with value only 1
or I want to count idxdaftar where this have kode with value 1 and 2
for example
1) the result count(idxdaftar) where kode with value only 1 = 1
2) the result count(idxdaftar) where kode with value 1 and 2 = 1
Help me, please...
You should be more specific about the logic behind it but in you can use conditional count using CASE expression like
sum(case when kode = 1 then 1 else 0 end)
If I got it right, try
select type, count(*)
from (
select idxdaftar, case when count(distinct kode) = count(distinct case when kode = 1 then kode end) then '1' else '1+2' end type
from (
select 50 idxdaftar, 1 kode
union all
select 51 idxdaftar, 1 kode
union all
select 50 idxdaftar, 2 kode
) tab
group by idxdaftar
having count(distinct kode) in (
count(distinct case when kode = 1 then kode end),
count(distinct case when kode in (1,2) then kode end))
) t
group by type
I think this is what you want:
select count(distinct case when kcode in (1, 2) then idxafter end)
from t;

joining with a group by and pivot

I have two tables as below
tbl1
id qNum
1 1
2 2
3 3
tbl2
id qNum displayNum
1 1 3
2 2 1
3 2 2
4 2 4
Ideally I need a sql results to look like this
qNum display1 display2 display3 display4
1 0 0 1 0
2 1 1 0 1
3 0 0 0 0
I have tried the following sql but this was not correct
SELECT
tbl1.qNum,
CASE when tbl2.displayNum=1 then 1 else 0 end AS filter1,
CASE when tbl2.displayNum=2 then 1 else 0 end AS filter2,
CASE when tbl2.displayNum=3 then 1 else 0 end AS filter3,
CASE when tbl2.displayNum=4 then 1 else 0 end AS filter4,
CASE when tbl2.displayNum=5 then 1 else 0 end AS filter5
FROM
tbl1
Left Join tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY
tbl1.qNum
Could anyone help a little please!!
You have use MAX function to pivot the table
Try this:
SELECT tbl1.qNum,
MAX(CASE WHEN tbl2.displayNum=1 THEN 1 ELSE 0 END) AS filter1,
MAX(CASE WHEN tbl2.displayNum=2 THEN 1 ELSE 0 END) AS filter2,
MAX(CASE WHEN tbl2.displayNum=3 THEN 1 ELSE 0 END) AS filter3,
MAX(CASE WHEN tbl2.displayNum=4 THEN 1 ELSE 0 END) AS filter4,
MAX(CASE WHEN tbl2.displayNum=5 THEN 1 ELSE 0 END) AS filter5
FROM tbl1
LEFT JOIN tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY tbl1.qNum
Your query is almost correct, you're just missing an aggregate function:
SELECT
tbl1.qNum,
MAX(CASE when tbl2.displayNum=1 then 1 else 0 end) AS filter1,
MAX(CASE when tbl2.displayNum=2 then 1 else 0 end) AS filter2,
MAX(CASE when tbl2.displayNum=3 then 1 else 0 end) AS filter3,
MAX(CASE when tbl2.displayNum=4 then 1 else 0 end) AS filter4,
MAX(CASE when tbl2.displayNum=5 then 1 else 0 end) AS filter5
FROM
tbl1
Left Join tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY
tbl1.qNum
The columns you select should always be either in the group by clause or an aggregate function should be applied to them. A group by "collapses" a group of rows and if you don't have an aggregate function on a column (which is not in the group by) a random row of that group is displayed.
Here you can read about the different aggregate functions: GROUP BY (Aggregate) Functions
The MAX() function in our case here returns the greatest value (note: not the row with the greatest value. You can also have a query like this: select min(col), max(col) from whatever).
I just want to point out that in MySQL, you can simplify the expression. It doesn't need a case statement because booleans are treated as integers with values of 0 and 1:
SELECT tbl1.qNum,
MAX(tbl2.displayNum = 1) AS filter1,
MAX(tbl2.displayNum = 2) AS filter2,
MAX(tbl2.displayNum = 3) AS filter3,
MAX(tbl2.displayNum = 4) AS filter4,
MAX(tbl2.displayNum = 5) AS filter5
FROM tbl1 Left Join
tbl2
ON tbl1.qNum = tbl2.qNum
GROUP BY tbl1.qNum;
Normally, I prefer going with ANSI standard syntax. I do, however, find this easier to read than the case syntax.
Also, you may not need tbl1 for the query, if all values you are interested in are already in tbl2.