How to get count of each value against unique id in Mysql - mysql

I Have below mentioned table:
Where Val column has 3 distinct value a,b & c.
ID Val
1 a
1 a
1 b
2 b
2 c
2 c
3 c
I want to get count of unique ids and count of ids for respective Val value (i.e a,b & c).
I am using query like this but it helps me to identify count for a single Val value at a time.
SELECT ID,COUNT(*)
FROM table1
WHERE Val='c' GROUP BY ID;
Required output:
ID count a b c
1 3 2 1 0
2 3 0 1 2
3 1 0 0 1

You can use group by and sum the count when val is equal to a,b or c. See below:
select id,
count(*) as `count`,
sum(case when val = 'a' then 1 else 0 end) as a,
sum(case when val = 'b' then 1 else 0 end) as b,
sum(case when val = 'c' then 1 else 0 end) as c
from yourTable
group by id;

Just use conditional aggregation:
select id, count(*), sum(val = 'a') as a, sum(val = 'b') as b, sum(val = 'c') as c
from table1
group by id;

Related

SQL : Summing the values in a column till first non zero values appears in other column?

Suppose, I have a table t1 looking like
id
value1
value2
wk_id
1
2
0
1
1
1
1
2
1
3
0
3
2
2
1
2
2
2
0
3
3
1
0
2
3
2
0
4
3
3
0
5
And I want to sum up the value1 till non-zero value appears on the value2 for first time.
End product must look like this:
id
value1
1
2
2
0
3
6
How to perform this in SQL?
If your MySQL version support window function you can try to use SUM window function with condition aggregate function be a flag to represent your logic (till non-zero value appears on the value2 for first time)
Then do condition aggregate function again.
Query #1
SELECT id,
SUM(CASE WHEN flag = 0 THEN value1 ELSE 0 END) value1
FROM (
SELECT *,
SUM(CASE WHEN value2 = 1 THEN -1 ELSE 0 END) OVER(PARTITION BY ID ORDER BY wk_id) flag
FROM T
) t1
GROUP BY id;
id
value1
1
2
2
0
3
6
View on DB Fiddle
WITH cte AS (
SELECT *,
CASE WHEN SUM(value2) OVER (partition by id ORDER BY wk_id) = 0
THEN SUM(value1) OVER (partition by id ORDER BY wk_id)
ELSE 0
END sum_value1
FROM test
ORDER BY id, wk_id
)
SELECT id, MAX(sum_value1) sum_value1
FROM cte
GROUP BY id;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0fcdca008e4a821f952de4d608434bcf
One option is a NOT EXISTS clause, looking for the stop row (the first row with value2 = 1).
select id, sum(value1)
from mytable
where not exists
(
select null
from mytable stoprow
where stoprow.id = mytable.id
and stoprow.wk_id <= mytable.wk_id
and stoprow.value2 = 1
)
group by id
order by id;
Aggregating on a calculated rolling total of value2 can also be done via a self-join.
select id
, sum(if(roll_tot_value2=0,value1,0)) as total
from
(
select t1a.id, t1a.wk_id, t1a.value1
, sum(t1b.value2) as roll_tot_value2
from t1 as t1a
join t1 as t1b
on t1b.id = t1a.id
and t1b.wk_id <= t1a.wk_id
group by t1a.id, t1a.wk_id, t1a.value1
) q
group by id;
id
total
1
2
2
0
3
6
Test on db<>fiddle here
You can use a subquery:
select t.id, coalesce(
(select sum(t2.value1) from t1 t2 where t2.value2 = 0 and t2.id = t.id
and (not exists (select 1 from t1 t3 where t3.value2 = 1 and t3.id = t.id)
or t2.wk_id < (select min(t4.wk_id) from t1 t4 where t4.id = t.id and t4.value2 = 1))), 0)
from t1 t group by t.id

MySQL group by for missing values

Given a table with the following data
ID Value
1 A
1 B
1 C
1 D
2 A
2 C
3 A
I would like to build a query that returns which values are missing from the id set based on value A being present. It can be assumed an ID for 'A' is always present.
Result:
ID | B | C | D
2 | 0 | 1 | 0
3 | 0 | 0 | 0
The values are A, B, C, D. In this example all values are there for ID 1 but the table reports that B is missing for both given that A is a value for ID 2 and so on.
I have a query to return which ID's are missing for a given value but I have not found a way to join all three together:
select id
from table_1
where id not in (
select id
from table_1
where value = 'B' #additional queries replacing 'B' with 'C' and 'D'
) and value = 'A'
order by id asc
Is it possible to combine those three separate queries in to a result table as I have laid out? I feel like this requires inner joins but have not been able to build out a query that works.
You could use conditional aggregation:
SELECT id,
SUM(Value = 'A') AS a,
SUM(Value = 'B') AS b,
SUM(Value = 'C') AS c,
SUM(Value = 'D') AS d
FROM tab
GROUP BY id;
DBFiddle Demo
Values list (A,B,C,D) has to be known in advance.
Skipping row if all values are present:
SELECT *
FROM (
SELECT id, SUM(Value = 'A') AS a,
SUM(Value = 'B') AS b,
SUM(Value = 'C') AS c,
SUM(Value = 'D') AS d
FROM tab
GROUP BY id
) sub
WHERE NOT (a>0 and b>0 and c>0 and d>0);
DBFiddle Demo2

Select count of different flags in a column in MySQL

I have a table:
id flag
1 Y
1 Y
1 Y
1 N
1 N
2 Y
2 N
2 N
3 Y
3 N
i want to do as select statement which will give me the following output.
id count_flag_Y count_flag_N
1 3 2
2 1 2
3 1 1
I was trying using the select case method but getting syntax error.
SELECT id,SUM(CASE WHEN flag= 'Y') as count_flag_Y,
SUM(CASE WHEN flag= 'N') as count_flag_N
from tablename
GROUP BY id
Is there any way to do it?
Your query was not far off, you only have a slight problem with the CASE expressions. Try this:
SELECT id,
SUM(CASE WHEN flag= 'Y' THEN 1 ELSE 0 END) AS count_flag_Y,
SUM(CASE WHEN flag= 'N' THEN 1 ELSE 0 END) AS count_flag_N
FROM tablename
GROUP BY id
You are very close, but in MySQL the CASE is not needed:
SELECT id, SUM(flag = 'Y') as count_flag_Y,
SUM(flag = 'N') as count_flag_N
FROM tablename
GROUP BY id;
MySQL treats boolean expressions like integers in a numeric context, with "1" for true and "0" for false.

How to get count of unique values in a column group by the primary key

I am new to sql and i have this problem in hand.
I have a table temp which has id and flag as its columns.
ID FLAG
-- ----
A 1
A 1
A 0
B 1
B 0
B 0
C 0
C 0
C 0
I need the 1's and 0's count with respect to each ID.
The desired output is
ID OnesCount ZerosCount
--- --------- ----------
A 2 1
B 1 2
C 0 3
I tried a lot i can get them individually by
select id,count(*) ZerosCount from temp where flag = 0 group by id
select id,count(*) OnesCount from temp where flag = 1 group by id
But do not understand how to join and get the desired output.
Can some one please help
In this specific case you can do like this:
select customer_id ID,
sum(pwr_flag) OnesCount,
sum(1-pwr_flag) ZerosCount
from temp_pwr
group by customer_id
In a more generic case you can use case when:
select customer_id ID,
sum(case pwr_flag when 1 then 1 else 0 end) OnesCount,
sum(case pwr_flag when 0 then 1 else 0 end) ZerosCount
sum(case pwr_flag when 17 then 1 else 0 end) SeventeensCount
from temp_pwr
group by customer_id
select customer_id,
count(case when pwr_flag = 0 then 1 end) ZerosCount,
count(case when pwr_flag = 1 then 1 end) OnessCount
from temp_pwr
group by customer_id

How to group repeated row values in a column

t_no name value
1 a 45
1 b 23
1 c 5
1 a 12
1 b 99
1 c 6
I need to show my above table as
no name value1 value2
1 a 45 12
1 b 23 99
1 c 5 6
You can't create dynamic columns in mysql alone, either in scripting language, or you can use group_concat to have them in one column:
SELECT to_no, name, GROUP_CONCAT(value)
FROM table GROUP BY to_no, name
result:
no name value
1 a 45,12
1 b 23,99
1 c 5,6
MySQL does not have a pivot function, but you can use an aggregate function with a CASE expression. Since you have multiple values for each t_no and name, then you could use user defined variables to assign a row number to each group of values:
select t_no, name,
max(case when rn=1 then value end) value1,
max(case when rn=2 then value end) value2
from
(
select t_no, name, value,
#rn:=case when #prev=t_no and #c=name then #rn else 0 end +1 rn,
#prev:=t_no,
#c:=name
from yourtable
cross join (select #rn:=0, #prev:=0, #c:=null) c
order by t_no, name
) d
group by t_no, name
order by t_no, name;
See SQL Fiddle with Demo