SQL Where condition in group by with 2 contradicting clauses - sql

I have a Table like so:
ID1|ID2|ID3|Enabled
1 1 0 1
1 1 1 1
1 1 2 1
2 1 1 1
2 1 2 1
2 1 3 1
3 1 0 0
3 1 1 1
3 1 2 1
4 1 0 1
4 1 0 1
4 1 0 1
I want to group by first ID1 then ID2 and select all ID1 where within each group, ID3 contains both 0 (If Enabled column is 1) and nonzero value. So the table provided will return -
ID1
1
SELECT ID1 From Table1
GROUP BY ID1, ID2
WHERE
???

You want a having clause, if your definition of group is based on ID1/ID2:
SELECT ID1, ID2
FROM Table1
GROUP BY ID1, ID2
HAVING SUM(CASE WHEN ID3 = 0 AND Enabled = 1 THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN ID3 <> 0 THEN 1 ELSE 0 END) > 0;

You need a group by with an alternative having as you would not be able to use having for id3 as id3 should be present in group by first to be used in having else ypu can use only aggregates in having. So, In order to make the id3 case work I have used here case when which is checking id3 if found as either 0 or 1 would be returning value as 1 in each such case. Therefore, the sum on top of case act as an aggregate in having hence would work as if sum obtained based on the cases comes as greater than or equal to 2 or more(if duplicates of 0 and 1) then output those rows of that partcular group.
select ID1
from Table1
where enabled = 1
group by ID1, ID2
having sum( case when ID3 in (1,0) then
1 else 0 end) >= 2

Related

Slicing table data based on days

Having the following data table:
col1
days
A
2
B
3
C
1
C
5
D
3
A
3
B
7
A
4
I want to transform it into:
col1
<=2days
<=5days
<=7days
A
1
2
0
B
0
1
1
C
1
1
0
D
0
1
0
I used the below query to achieve this:
select col1,
CASE WHEN days <=2 then count(days) as "<=2days",
CASE WHEN days > 2 and days <=5 then count(days) as "<=5days",
CASE WHEN days > 5 and days <=7 then count(days) as "<=7days"
from tableA group by col1,days
But it returns a result like the following:
col1
<=2days
<=5days
<=7days
A
1
0
0
A
0
2
0
B
0
1
0
B
0
0
1
C
0
1
0
C
1
0
0
D
0
1
0
Can someone please help here?
You could use conditional aggregation as the following:
SELECT col1,
COUNT(CASE WHEN days<=2 THEN 1 END) AS '<=2days',
COUNT(CASE WHEN days<=5 and days>2 THEN 1 END) AS '<=5days',
COUNT(CASE WHEN days<=7 and days>5 THEN 1 END) AS '<=7days'
FROM tableA
GROUP BY col1
ORDER BY col1
See a demo on MySQL.

Is there a way to get max consecutive counts of 1s across columns in SQL?

Is there a way to get maximum consecutive counts across columns in SQL? I'm looking for longest duration of survival.
For example, if I have a dataset that looks like this
ID T1 T2 T3 T4 T5 T6 T7 T8 T9
1 1 1 0 0 0 1 1 1 1
2 0 0 0 1 1 1 1 1 0
3 0 1 0 1 0 1 1 0 0
4 0 1 0 0 0 0 0 0 0
5 0 1 1 0 0 0 0 0 0
6 1 0 1 1 0 1 1 1 0
I want to add a column to get the maximum consecutive 1s across the columns T1-T9 so it would look like this
ID T1 T2 T3 T4 T5 T6 T7 T8 T9 MAX
1 1 1 0 0 0 1 1 1 1 4
2 0 0 0 1 1 1 1 1 0 5
3 0 1 0 1 0 1 1 0 0 2
4 0 1 0 0 0 0 0 0 0 1
5 0 1 1 0 0 0 0 0 0 2
6 1 0 1 1 0 1 1 1 0 3
**The below code is a way to get maximum consecutive counts across Column in MySQL I think you want across the Row **
create table t(id integer,t1 integer,t2 integer,t3 integer,t4 integer,t5 integer,t6 integer,t7 integer,t8 integer,t9 integer);
insert into t values(1,1,0,1,0,1,1,0,0,0),(2,0,0,1,1,1,0,0,0,0),(3,1,0,1,1,1,1,0,0,0);
WITH CTE1 AS
(
SELECT id , ROW_NUMBER() OVER (ORDER BY id) Rnk FROM t
)
,CTE2 AS
(
SELECT *, CASE WHEN id-1 = LAG(id) OVER(ORDER BY rnk) THEN 0
ELSE 1 END cols FROM CTE1 c2
)
,CTE3 AS
(
SELECT *, SUM(cols) OVER(ORDER BY rnk) Grouper FROM CTE2 c2
)
SELECT * FROM
(
SELECT COUNT(*) Counts FROM CTE3 GROUP BY Grouper
)r
ORDER BY Counts DESC ;
I think the simplest method in proc sql might be a brute force approach:
select t.*,
(case when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%111111111%' then 9
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%11111111%' then 8
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%1111111%' then 7
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%111111%' then 6
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%11111%' then 5
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%1111%' then 4
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%111%' then 3
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%11%' then 2
when t1||t2||t3||t4||t5||t6||t7||t8||t9 like '%1%' then 1
else 0
end) as max
from t;
Here is a db<>fiddle illustrating the logic using Postgres.

How to count more than one value in ms sql

I have a table with a column named direction. This columns has just 1 or 0 int value. For every 1 or zero there is and ID couple. For example:
ID1 ID2 direction
1 2 1
2 3 0
2 4 1
4 1 1
1 2 0
2 3 1
I need a select query in order to take 0 counts and 1 counts for every ID1 and ID2 pair. How can I do that?
Edit:
Result table should look like this: (Numbers does not match with above example)
ID1 ID2 0count 1count
1 2 1 4
2 3 2 2
2 2 1 1
Conditional aggregation is your friend:
SELECT ID1,
ID2,
SUM(CASE WHEN direction = 0 THEN 1 ELSE 0 END) As CountDirection0,
SUM(CASE WHEN direction = 1 THEN 1 ELSE 0 END) As CountDirection1,
FROM Table
GROUP BY ID1, ID2

SQL using GROUP BY and COUNT

I created the MariaDB(10.1.21) table named 'group_test' and saved some data as below.
Group Item Value1 Value2 Value3
A a1 1 0 0
A a2 1 1 1
A a3 1 1 2
B b1 1 1 0
B b2 1 1 1
B b3 1 0 0
B b4 1 1 3
C c1 1 1 0
C c2 1 1 1
Using a query, I want to make the result as below at once.
Group Items Value1_1 Value2_1 Value3_1
A 3 3 2 1
B 4 4 3 1
C 2 2 2 1
Items means the total number of 'Item' in the 'Group'.
ValueN_1 means the total number of 'ValueN' value equal to 1 in the 'Group'.
I think I would use GROUP BY and COUNT but I don't know exactly what to do.
How do I write SQL to get the above results in one query?
Thanks.
Simply do a GROUP BY. Since Value1 to Value3 are only 0's and 1's, you can use SUM() to count the 1's.
select Group, count(Item), sum(Value1), sum(Value2), sum(Value3)
from tablename
group by Group
Edit: "ValueN can have a value from 0 to 4":
select Group,
count(Item),
sum(case when Value1 = 1 then 1 else 0 end) Value1_1,
sum(case when Value2 = 1 then 1 else 0 end) Value2_1,
sum(case when Value3 = 1 then 1 else 0 end) Value3_1
from tablename
group by Group
Assuming value1, value2 and value3 can only be either 0 or 1, you can write it like this
select Group,
count(*) as Items,
sum(value1) as Value1_1,
sum(value2) as Value2_1,
sum(value3) as Value3_1
from yourTable t1
group by Group
If that's not the case, you will have to use a case in the sum
select Group,
count(*) as Items,
sum(case when value1 = 1 then 1 else 0 end) as Value1_1,
sum(case when value2 = 1 then 1 else 0 end) as Value2_1,
sum(case when value3 = 1 then 1 else 0 end) as Value3_1
from yourTable t1
group by Group
Use GROUP BY clause and SUM aggregate function in SELECT statement
SELECT *
FROM
(
SELECT [Group], count(Item) Item, sum(Value1) Value1, sum(Value2) Value2,
sum(Value3) Value3
FROM Your_tableName
GROUP BY [Group]
) A

How can we count sub query use group by without pivot?

I need to create query that has below result.
I add my table for example for better understanding.
QTable:
QID Name
-------
1 x
1 y
2 z
FTable:
QID FID
-------
1 1
1 2
2 3
Inner join with :
FID Type
-------
1 1
1 2
1 3
1 4
2 2
2 3
2 3
3 1
3 3
3 3
I need to result like this:
result:
QID FID-Count Type(1)-count Type(2)-count Type(3)-count Type(4)-count
-----------------------------------------------------------------
1 2 1 2 3 1
2 1 1 0 2 0
Thank u for help.
Ususally you can emulate a pivot with GROUP BY and SUM+CASE:
SELECT
T1.QID,
COUNT(DISTINCT T1.FID) as FIDCOUNT,
SUM(CASE WHEN Type=1 THEN 1 ELSE 0 END) as Type1Cnt,
SUM(CASE WHEN Type=2 THEN 1 ELSE 0 END) as Type2Cnt,
SUM(CASE WHEN Type=3 THEN 1 ELSE 0 END) as Type3Cnt,
SUM(CASE WHEN Type=4 THEN 1 ELSE 0 END) as Type4Cnt
FROM QFTable as T1
JOIN T2 ON
T1.FID=T2.FID
GROUP BY T1.QID
ORDER BY QID
SQLFiddle demo