Slicing table data based on days - sql

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.

Related

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.

SQL Server - Show All possible Values and Count Them

I have the following table:
IdSce Year NoIte Value
1 0 1 1
1 0 2 5
1 0 3 1
1 1 1 2
1 1 2 3
1 1 3 2
2 0 1 4
2 0 2 4
2 0 3 1
2 1 1 2
2 1 2 4
2 1 3 3
I want to group by IdSce and Year, and show each possible value and count how many time each value appears like this:
IdSce Year Value1 Value2 Value3 Value4 Value5
1 0 2 0 0 0 1
1 1 0 2 1 0 0
2 0 1 0 0 2 0
2 1 0 1 1 1 0
Thanks !
EDIT
shawnt00 is really close to what I want, but I'm looking to do it as dynamic as possible, meaning if I have 10 different values for the column value, I will be missing information in my table. Therefore, if I have 10 different values, I want 10 new columns (value1, value2, ... , value10)
This is what I've tried so far:
SELECT IdSce
,Year
,SUM(CASE WHEN Value >= 0 and Value < 1 THEN 1 else 0 end) Zero
,SUM(CASE WHEN Value >= 1 and Value < 2 THEN 1 else 0 end) One
,SUM(CASE WHEN Value >= 2 and Value < 3 THEN 1 else 0 end) Two
,SUM(CASE WHEN Value >= 3 and Value < 4 THEN 1 else 0 end) Three
,SUM(CASE WHEN Value >= 4 and Value < 5 THEN 1 else 0 end) Four
,SUM(CASE WHEN Value >= 5 THEN 1 else 0 end) FiveMore
,SUM(CASE WHEN Value >= 0 THEN 1 else 0 end) Total
FROM Table
GROUP BY IdSce
,Year
Thanks for the help again!
Ok, I'll do it!
select IdSce, "Year"
count(case when Value = 1 then 1 end) as "1",
count(case when Value = 2 then 1 end) as "2",
count(case when Value = 3 then 1 end) as "3",
count(case when Value = 4 then 1 end) as "4",
count(case when Value = 5 then 1 end) as "5"
from T
group by IdSce, "Year"
I think you'll often find this filed under "conditional aggregation". SQL Server has a proprietary syntax that uses pivot if you want to look into that also.

How to return one single row from groupped by columns

I have table like this
ID Specified TIN
-----------------
1 0 tin1
2 0 tin1
3 1 tin1
4 0 tin2
5 0 tin3
6 1 tin3
7 1 tin3
I need to count rows groupped by TIN, Specified columns - but result should one row for each TIN:
TIN ZEROSpecified NOTZEROSpecified
tin1 2 1
tin2 0 1
tin3 1 2
Important notice - i have only 2 values for Specified column - 0 and 1
SELECT TIN,
SUM(case when Specified=0 then 1 else 0 end) as ZeroSpecified,
SUM(case when Specified<>0 then 1 else 0 end) as NOTZEROSpecified
FROM table
GROUP BY TIN
Pretty Simple;
SELECT
TIN
,SUM(CASE WHEN Specified = 0 THEN 1 ELSE 0 END) ZEROSpecified
,SUM(CASE WHEN Specified <> 0 THEN 1 ELSE 0 END) NotZEROSpecified
FROM TableName
GROUP BY TIN

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

SQL selecting from a particular duplicate row

Hi all I have a sql query
SELECT FKid1, FKID2, a, b, c
from [source]
where FKID1 = 3
which returns the following data set so
(hope formatting holds)
FKID1 FKID2 A B C
3 40297 0 0 2
3 40297 0 100 1
3 40325 0 0 2
3 40325 0 0 3
3 40325 0 10 -1
3 40348 0 10 3
3 40391 0 10 -1
3 40392 0 10 -1
3 40501 0 10 -1
3 40501 0 0 2
I'm trying to improve this query so that if there are 2 rows with duplicate FKID1 and FKID2 values, it will pick the column B value from a particular row as follows...
if there is a row with C = -1 use the B value in this row and ignore others.
if there are 2 rows with C <> -1 then pick the MAX(B) value.
For rows that are not duplicated, return as normal.
IE the results should look as follows...
FKID1 FKID2 A B C
3 40297 0 100 1
3 40325 0 10 -1
3 40348 0 10 3
3 40391 0 10 -1
3 40392 0 10 -1
3 40501 0 10 -1
the correct values selected for the B column and no dupes.
We have a solution at the moment, but I think it's overcomplicated and wondered if anyone had any ideas?
Thanks.
One way
;WITH cte As
(
SELECT FKid1, FKID2, a, b, c,
ROW_NUMBER() OVER (PARTITION BY FKID1, FKID2
ORDER BY CASE WHEN C = -1 THEN 0 ELSE 1 END ASC, B DESC) AS RN
from [source]
where FKID1 = 3
)
SELECT FKid1, FKID2, a, b, c
FROM cte
WHERE RN=1
Select T1.FKID1, T1.FKID2
, Min(A) As A
, Case
When Count(*) = 2 And NegCB.B Is Not Null Then Max(NegCB.B)
Else Max(B)
End As B
, Min(C) As C
From Source As T1
Outer Apply (
Select T3.B
From Source As T3
Where T2.FKID1 = T1.FKID1
And T2.FKID2 = T1.FKID2
And T2.C = -1
) As NegCB
Where FKID1= 3
Group By T1.FKID1, T1.FKID2