sql: long to wide format without using PIVOT - sql

I have a table like the following:
user_id time_id val0 val1 val2 actual_value score
1 1 1 0 0 0 0.6
1 1 0 1 0 1 0.4
1 1 0 0 1 2 0.3
1 2 1 0 0 0 0.7
1 2 0 1 0 1 0.4
1 2 0 0 1 2 0.3
2 1 1 0 0 0 0.9
2 1 0 1 0 1 0.5
2 1 0 0 1 2 0.4
I want to convert the data to wide format like the following:
user_id time_id score_0 score_1 score_2
1 1 0.6. 0.3. 0.3
1 2 0.7. 0.4. 0.3
2 1 0.9. 0.5. 0.4
the SQL I used does not have a pivot choice so I am wondering how to convert the long format to wide without using PIVOT.

If I understand your question correctly, you can do conditional aggregation:
select
user_id,
time_id,
max(case when val0 = 1 then score end) score0,
max(case when val1 = 1 then score end) score1,
max(case when val2 = 1 then score end) score2
from mytable
group by user_id, time_id
Maybe you want to use actual_value to pivot instead of the val[n] columns:
select
user_id,
time_id,
max(case when actual_value = 0 then score end) score0,
max(case when actual_value = 1 then score end) score1,
max(case when actual_value = 2 then score end) score2
from mytable
group by user_id, time_id

You can use conditional aggregation:
select user_id, time_id,
max(case when actual_value = 0 then score end) as score_0,
max(case when actual_value = 1 then score end) as score_1,
max(case when actual_value = 2 then score end) as score_2
from t
group by user_id, time_id;

Related

SQL: select max value when converting from long to wide format

I have a table like the following and I need to convert it from this long format to wide and at the same time, I need to select the action value corresponding to max score:
user_id time_id val0 val1 val2 action_value score
1 1 1 0 0 0 0.6
1 1 0 1 0 1 0.3
1 1 0 0 1 2 0.3
1 2 1 0 0 0 0.7
1 2 0 1 0 1 0.4
1 2 0 0 1 2 0.3
2 1 1 0 0 0 0.4
2 1 0 1 0 1 0.5
2 1 0 0 1 2 0.4
the desired output is:
user_id time_id score_0 score_1 score_2 action_value
1 1 0.6. 0.3. 0.3 0
1 2 0.7. 0.4 0.3. 0
2 1 0.4 0.5 0.4. 1
the SQL I use do not have PIVOT, so I cannot use PIVOT. And I know that I can use conditional aggregation to convert the data from long format to wide format but I am not sure how I can also select the action_value column corresponding to the max score.
You could use a subquery, then greatest() (if your database supports it):
select
t.*,
case greatest(score0, score1, score2)
when score0 then 0
when score1 then 1
when score2 then 2
end action_value
from (
select
user_id,
time_id,
max(case when actual_value = 0 then score end) score0,
max(case when actual_value = 1 then score end) score1,
max(case when actual_value = 2 then score end) score2
from mytable
group by user_id, time_id
) t

Convert Rows into column without using Pivot

I have a data set, but the sample data will look like the below one:
Country Date Category X Y
IN 2011-11-22 B 1 0
BA 2010-11-23 B 11 0.2
IN 2011-11-22 A 1 0
BA 2011-11-23 A 1 1
IN 2011-07-28 A 1 0
want to convert it into : Output
Country Date B_X B_Y A_X A_Y
IN 2011-11-22 1 0 1 0
BA 2010-11-23 11 0.2 1 1
IN 2011-07-28 0 0 1 0
I have tried using case but it is not giving me a desired output, can anyone help!!
I think you just want to aggregate by country/date and use conditional aggregation:
select country, date,
sum(case when category = 'B' then x end) as x_b,
sum(case when category = 'B' then y end) as y_b,
sum(case when category = 'A' then x end) as x_a,
sum(case when category = 'A' then y end) as y_a
from t
group by country, date;

Pivot and Sum of values in column based on specific row condition

I have a sample table like this:
DaysInOp Zone_id DailyAvg RunNumber
0 9 5996.79891226986 1
0 15 0 1
0 3 12549.5152623033 1
0 12 -8400.75508952542 1
0 6 24766.7738319152 1
0 7 11737.3698582701 1
0 1 26395.0374347879 1
0 18 0.0218623184855433 1
0 10 1965.53524850589 1
0 4 9499.54051554152 1
0 13 6158.45142253444 1
Where DaysinOp could be from 0-300
and Zone ID=1-20 and DailyAvg= Variable and RunNumber =1-5
I would like output like:
Day # Run 1 Weight (lbs) Run 2 Weight (lbs) Run 3 Weight (lbs) Run 4 Weight (lbs)
0 15 5 55 1
1 17 16 612 34
2 19 55 1100 56
3 22 100 1230 456
Etc. … … … …
Where Each run weight is Sum of daily avg values of Zone ID (1-10).
Please let me know if this is possible.
I am trying pivot with sum condition? Any hints will be appreciated.
SELECT
DaysInOp,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 1 THEN DailyAvg END) AS Run1Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 2 THEN DailyAvg END) AS Run2Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 3 THEN DailyAvg END) AS Run3Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 4 THEN DailyAvg END) AS Run4Weight,
SUM(CASE WHEN Zone_id BETWEEN 1 AND 10
AND RunNumber = 5 THEN DailyAvg END) AS Run5Weight
FROM
yourTable
GROUP BY
DaysInOp
Can be simplified by moving the Zone_id BETWEEN 1 AND 10 to a WHERE clause. If a day has no records in those zones, however, it won't appear in the results.
SELECT
DaysInOp,
SUM(CASE WHEN RunNumber = 1 THEN DailyAvg END) AS Run1Weight,
SUM(CASE WHEN RunNumber = 2 THEN DailyAvg END) AS Run2Weight,
SUM(CASE WHEN RunNumber = 3 THEN DailyAvg END) AS Run3Weight,
SUM(CASE WHEN RunNumber = 4 THEN DailyAvg END) AS Run4Weight,
SUM(CASE WHEN RunNumber = 5 THEN DailyAvg END) AS Run5Weight
FROM
yourTable
WHERE
Zone_id BETWEEN 1 AND 10
GROUP BY
DaysInOp
#MatBailie provided the manual pivot, here's the same query using the pivot operator:
with t1 as (
select DaysInOp
, case when zone_id between 1 and 10 then dailyavg end rw
, RunNumber
from table1
)
select DaysInOp [Day #]
, [1] [Run 1 Weight (lbs)]
, [2] [Run 2 Weight (lbs)]
, [3] [Run 3 Weight (lbs)]
, [4] [Run 4 Weight (lbs)]
, [5] [Run 5 Weight (lbs)]
from t1
pivot (sum(rw)
for RunNumber in ([1],[2],[3],[4],[5])) pvt

Rounding and getting a count of the number of times a number appears? SQL

I have the following data:
-1.25
-0.5
0
0
1.25
0.75
1.25
2
2
2
2
I'm trying to consolidate these numbers while also rounding them, and making anything that is negative go to 0.
Here is what I have so far:
SELECT
RawScore,
Count(*) AS Freq
FROM TestScores
GROUP BY RawScore
This returns
RawScore Freq
-1.25 1
-0.5 1
0 2
0.75 1
1.25 1
2 4
Is there a way to get this instead?
RawScore Freq
0 4
1 2
2 4
You can do:
select (case when rawScore < 0 then 0
else round(rawScore, 0)
end) as nolongerrawScore,
count(*)
from TestScores
group by (case when rawScore < 0 then 0
else round(rawScore, 0)
end)
order by nolongerrawScore;
SELECT
FLOOR(ABS(RawScore)),
Count(*) AS Freq
FROM TestScores
GROUP BY FLOOR(ABS(RawScore))

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.