Convert Rows into column without using Pivot - sql

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;

Related

Group by and divide

I have the table below on sql of accounting accounts (A is a cost account and B a headcount ) , and cc as cost center . So what i want to do is divide the amount of account A over account B for each cc
Account
cc
Amount
A
x
1
A
y
2
B
z
4
B
y
1
A
z
1
B
x
2
So the result would be :
Account
cc
Amount
A
x
1 /2
A
y
2
B
z
0
B
y
0
A
z
1 /4
B
x
0
I was thinking about a group by but Im a very beginner in sql and don't know how to use it thanks in advance for your help!
For the results you specify, you can use window functions:
select t.*,
(case when account = 'A'
then amount * 1.0 / sum(case when account = 'B' then amount end) over (partition by cc)
else 0
end) as ratio
from t;
I would just use a regular group by with some cases:
with cc_amts as (
select cc,
sum(case when account = 'A' then amount else 0 end) amt_a,
sum(case when account = 'B' then amount else 0 end) amt_b
from t
group by cc)
select cc, amt_a / amt_b
from cc_amts;

sql: long to wide format without using PIVOT

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;

Concetating results from Oracle table with several criterias

This is a tough one. I've read about concatating values from multible rows in a table, but can't find anything on how to go about the task set before me.
I'm not an oracle-man, and untill now have only made simple select queries, so I'm at a loss here.
In a huge oracle database table (severel hundred millions of rows) containing laboratory results, I need to select information on specific requisitions, that meet a specific criteria.
Criteria: For the same ReqNo, Analysis A B and C must be present with an answer, if they are, any instance of the answer to analysis X, Y or Z should be selected
Table contents:
ReqNo Ana Answer
1 A 7
1 B 14
1 C 18
1 X 250
2 A 8
2 X 35
2 Y 125
3 A 8
3 B 16
3 C 20
3 Z 100
4 X 115
4 Y 355
5 A 6
5 B 15
5 C 22
5 X 300
5 Y 108
5 C 88
Desired result:
ReqNo A B C X Y Z
1 7 14 18 250
3 8 16 20 100
5 6 15 22 300 108 88
leaving out ReqNo 2 and 4, since they don't meet the A/B/C criteria.
Is that even possible?
You may first filter the records that have all 3 (A,B and C) and then use PIVOT to convert them to columns for those which satisfy the criteria.
with req
AS
(
select reqno from t where ana IN ('A','B','C')
GROUP BY reqno HAVING
count(DISTINCT ana) = 3
)
select * FROM
(
select * from t where
exists ( select 1 from req r where t.reqno = r.reqno )
)
PIVOT(
min(answer) for ana in ('A' as A, 'B' as B, 'C' as C,
'X' as X, 'Y' as Y, 'Z' as Z)
) ORDER BY reqno;
Demo
I would just use conditional aggregation:
select reqno,
max(case when Ana = 'A' then Answer end) as a,
max(case when Ana = 'B' then Answer end) as b,
max(case when Ana = 'C' then Answer end) as c,
max(case when Ana = 'X' then Answer end) as x,
max(case when Ana = 'Y' then Answer end) as y,
max(case when Ana = 'Z' then Answer end) as z
from t
group by reqno
having sum(case when Ana = 'A' then 1 else 0 end) > 0 and
sum(case when Ana = 'B' then 1 else 0 end) > 0 and
sum(case when Ana = 'C' then 1 else 0 end) > 0 ;
Given that you don't seem to have duplicates, you can simplify the having to:
having sum(case when Ana in ('A', 'B', 'C') then 1 else 0 end) = 3

How can I get the count depending on the column value in SQL Server

I have this table in SQL Server
name type date
aaa A 2016-05-05
aaa A 2016-05-22
aaa B 2016-05-21
bbb A 2016-05-15
bbb B 2016-05-01
and I want to make a query to get this result
name count(type)
aaa 2.5
bbb 1.5
NB : for A the count must increase with 1, and for B with 0.5 because I have this rule :
count(type)=count(A)+count(B)/2
Try this:
SELECT SUM(CASE type WHEN 'A' THEN 1.0 WHEN 'B' THEN 0.5 END)
FROM mytable
GROUP BY name
SELECT
SUM(
CASE type
WHEN 'B' THEN 0.5
WHEN 'A' THEN 1
END)
FROM <Table Name>
GROUP BY name
You can use CASE to do a calculation like follows:
SELECT SUM(CASE
WHEN Type = 'A'
THEN 1
ELSE 0
END) as SumA, SUM(CASE
WHEN Type = 'B'
THEN 0.5
ELSE 0
END) as Sum220
FROM Your Table

How to group sums by weekday in MySQL?

I have a table like this:
id | timestamp | type
-----------------------
1 2010-11-20 A
2 2010-11-20 A
3 2010-11-20 B
4 2010-11-21 A
5 2010-11-21 C
6 2010-11-27 B
and I need to count the rows for each type, grouped by weekday; like this:
weekday | A | B | C
--------------------------
5 2 2 0 -- the B column equals 2 because nov 20 and nov 27 are saturday
6 1 0 1
What would be the simplest solution for this?
I don't mind using views, variables, subqueries, etc.
Use:
SELECT WEEKDAY(t.timestamp) AS weekday,
SUM(CASE WHEN t.type = 'A' THEN 1 ELSE 0 END) AS a,
SUM(CASE WHEN t.type = 'B' THEN 1 ELSE 0 END) AS b,
SUM(CASE WHEN t.type = 'C' THEN 1 ELSE 0 END) AS c
FROM YOUR_TABLE t
GROUP BY WEEKDAY(t.timestamp)