Group by and divide - sql

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;

Related

Simple SQL that I am stuck on

What percent of customers are reward members?
ID Reward Member
1 y
2 y
3 n
4 y
5 n
Count how many are members, divide by total number of customers and multiply by 100.
SELECT sum(case when RewardMember = 'y' then 1 else 0 end)*100.0/count(*) as percentage
FROM Customers
You can use COUNT():
select
1.0 *
count(case when reward_member = 'y' then 1 else 0 end)
/ count(*)
from t
I would use conditional aggregation:
select avg( case when rewardmember = 'y' then 1.0 else 0 end) as ratio
from t;
Some databases allow shorter syntax, such as:
select avg( rewardmember = 'y' )
from t;
or:
select avg( (rewardmember = 'y')::int )
from 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;

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

Best way to do a Count in TSQL

I am not so good in TSQL and i want to write a report in this manner:
input: Table A
ID Company Product Flag
1 A Car Y
2 A Van N
3 B Van Y
4 A Part N
Output
Company Y N
A 1 2
B 1 0
if one can assist in TSQL...
You could use conditional aggregation:
SELECT Company
,SUM(CASE WHEN Flag = 'Y' THEN 1 ELSE 0 END) AS Y
,SUM(CASE WHEN Flag = 'N' THEN 1 ELSE 0 END) AS N
FROM tab
GROUP BY Company
You are looking for conditional aggregation:
select company,
sum(case when flag = 'Y' then 1 else 0 end) as num_y,
sum(case when flag = 'N' then 1 else 0 end) as num_n
from t
group by company;
You can use CASE expressions (the people call it "conditional aggregation") to count the flagged products per customer like this (which will ignore a record when the Product column is empty):
SELECT Company
, COUNT(CASE Flag WHEN 'Y' THEN Product END) AS Y
, COUNT(CASE Flag WHEN 'N' THEN Product END) AS N
FROM YourTable
GROUP BY Company;
Or you can use this PIVOT query, which is a short form of writing the above:
SELECT Company, Y, N
FROM (SELECT Company, Product, Flag FROM YourTable) AS src
PIVOT (COUNT(Product) FOR Flag IN (Y, N)) AS pvt;
use case when
select company,
sum(case when flag='Y' then 1 else 0 end) as Y,
sum(case when flag='N' then 1 else 0 end) as N from tabe_data
group by company

conditional aggregation on two different groups in SQL

Here is my data
COUNTYID POLLUTANT TYPE EMISSION
1 A 1
1 A 2
1 B 1
1 B 2
2 A 1
2 A 2
2 B 1
2 B 2
3 A 1
3 A 2
3 B 1
3 B 2
if I do
SELECT sum(EMISSION) from table where POLLUTANT = 'A' group by COUNTYID;
I would get pollution from Polutant 'A'. how can I write a query to get following data:
column 1 with sum of A, column 2 with sum of B, column 3 with sum of A and B?
Thank you
You can use case for filter the value you need
select COUNTYID, sum(case when POLLUTANT='A'then EMISSION else 0 END) tot_a
, sum(case when POLLUTANT='B'then EMISSION else 0 END) tot_b
, sum(EMISSION) tot_a_b
from my_table
group by COUNTYID
You can use conditional aggregation. This moves the filtering conditions from the where clause to the sum()s:
select countyid,
sum(case when emission = 'A' then emission else 0 end) as A,
sum(case when emission = 'B' then emission else 0 end) as B,
sum(emission) as total
from t
group by countyid;
I would like to give some idea. We can use pivot table for answer your question
SELECT * from dbo.[Table_1]
PIVOT
(Sum([type_emmssion]) for [polutant] in ([A], [B]) ) as PivotTable
group by [CountryId] ;
you have to use case statemet:
SELECT
SUM( CASE WHEN POLLUTANT = 'A' THEN EMISSION ELSE 0 END) AS A_EMISSION
SUM( CASE WHEN POLLUTANT = 'B' THEN EMISSION ELSE 0 END) AS B_EMISSION
SUM(EMISSION) AS total_emission
FROM table
GROUP BY COUNTYID;