SQL pivot unpivot query - sql

I don't have much experience with pivot/unpivot and could use some help. I have a SQL query with data as :
Category Account Name Value
001 1234 BALANCE_01 800
001 1234 BALANCE_02 1000
001 1234 BALANCE_03 1500
001 4567 BALANCE_01 900
001 4567 BALANCE_02 1200
001 4567 BALANCE_03 800
I need it to appear as:
Category Account BALANCE_01 BALANCE_02 BALANCE_03
001 1234 800 1000 1500
001 4567 900 1200 800
How do I do this?
Thanks,
Marcie

One way is to do this is by using conditional aggregation:
SELECT Category,
Account,
MAX(CASE WHEN Name = 'BALANCE_01' THEN Value ELSE NULL END) AS BALANCE_01,
MAX(CASE WHEN Name = 'BALANCE_02' THEN Value ELSE NULL END) AS BALANCE_02,
MAX(CASE WHEN Name = 'BALANCE_03' THEN Value ELSE NULL END) AS BALANCE_03
FROM Table
GROUP BY Category, Account

I would just just a group by
SELECT Category, Account,
SUM(CASE WHEN NAME='BALANCE_1' THEN Value ELSE 0 END) AS BALANCE_1,
SUM(CASE WHEN NAME='BALANCE_2' THEN Value ELSE 0 END) AS BALANCE_2,
SUM(CASE WHEN NAME='BALANCE_3' THEN Value ELSE 0 END) AS BALANCE_3
FROM Your_Table_You_Did_Not_Name
GROUP BY Category, Account
Note, if you have more than one row with the same Category, Account and Name this will fail -- but you don't tell us how to handle that.

Related

SQL Query two values for each record

I'm trying to query a customers table to get the total number of accounts per rep grouped by whether they were created this year or before.
CUSTOMER NAME
ACCOUNT REP
DATE CREATED
The query I'm trying to return would look like.
REP | NEW_ACCOUNTS | OLD_ACCOUNTS | TOTAL
-----------------------------------------
Tom | 100 | 12 | 112
Ted | 15 | 1 | 16
The query I've written looks as follows.
SELECT REP, CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END AS ThisYear
FROM CUSTOMERS
GROUP BY REP, DATE_CREATED
Unfortunately, this is giving me
REP | ThisYear
-----------------------------------------
Tom | 1
Ted | 0
Tom | 0
Ted | 1
Ted | 1
I think you want conditional aggregation:
SELECT REP,
SUM(CASE WHEN YEAR(GETDATE()) = YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS NEW_ACCOUNTS,
SUM(CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS OLD_ACCOUNTS,
COUNT(*) as TOTAL
FROM CUSTOMERS
GROUP BY REP;
This assumes that creation dates are not in the future -- a reasonable assumption.
If you want one row per REP, then the only column in the GROUP BY should be REP.
You can want conditional aggregation :
SELECT REP,
SUM(CASE WHEN YEAR(GETDATE()) = YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS NEW_ACCOUNTS,
SUM(CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS OLD_ACCOUNTS, COUNT(*) AS TOTAL
FROM CUSTOMERS
GROUP BY REP;

sql select and replace

I have a query that will show all the client information, and there is a column called sex, which 1 is female, 0 is male. How can I do another select on this result, that turn all the female record, turn the 1 to 100, male to 101? ( 1 and 0 in the first query, they are bit, in the second they are nvarchar) (Mssql)
select * from tblClientInfo
001 Derrick 0
002 Mary 1
then, turn it to
001 Derrick 100
002 Mary 101
You can use case:
select (case when male = 0 then '100' else '101' end)

Max and min both in a Group BY

I have requirement where I need to pull Max of data when > 0 and Min of data when < 0. And the tricky part is it should be in a same column. Example as follows:
Below Query:
SELECT A.employee_id, paycheck_number
max ( CASE
WHEN B.special = 'XXT' THEN B.AMOUNT
ELSE 0
END ) AMOUNT,
max ( CASE
WHEN B.special = 'XXH' THEN B.hrs1
ELSE 0
END ) HRS1
FROM Table1 A,
table2 B
LEFT OUTER JOIN table3 C
ON B.company = C.company
WHERE A .employee_id = '123456789'
GROUP BY A.employee_id, paycheck_number
ORDER BY 1
Returns:
EMPLOYEE_ID AMOUNT HRS1 paycheck_number
123456789 2799.82 134.84 1234
123456789 832.86 40 4321
123456789 0 0 5678
If removed the group by the data is :
EMPLOYEE_ID AMOUNT HRS1 paycheck_number
123456789 0 134.84 1234
123456789 2799.82 0 1234
123456789 0 40 4321
123456789 832.86 0 4321
123456789 0 -40 5678
123456789 -832.86 0 5678
Whereas I want:
EMPLOYEE_ID AMOUNT HRS1 paycheck_number
123456789 2799.82 134.84 1234
123456789 832.86 40 4321
123456789 -832.86 -40 5678
It looks simple but when I try It doesn't work.
In Oracle you get the value for the maximum absolute amount via KEEP DENSE_RANK FIRST/LAST:
max(value) keep (dense_rank last order by abs(value))
However, when there is always only the one non-zero value in one record and zeros or nulls in the other records to consider, you could simply add them:
sum(value)
In your case where only one record actually contains a value, you are creating the zero entries yourself and thus get 0 instead of, say, -40 when asking for the maximum value. Remove the ELSE branches that create the interfering zeros, and MAX will get you the correct value. E.g.:
max(case when b.special = 'XXT' then b.amount end) as amount

transpose rows to columns in db2

I have a query output as below
Customer policytype plan amount
Sam ulip P1 250
Sam ulife u1 435
Sam Ulip P2 370
Hazar Ulip P1 679
Hazar Ulife u1 567
And so on ....
I need to transpose above output as follows
Customer ulip ulife
Sam 250 435
Sam 370 Null
Hazar 679 567
Can someone help me to achieve above result in db2
Use conditional Aggregate
SELECT customer,
Max(CASE WHEN policytype = 'ulip' THEN amount END) AS ulip,
Max(CASE WHEN policytype = 'ulife' THEN amount END) AS ulife
FROM Youratable
GROUP BY customer,
CASE WHEN plan IN ( 'p1', 'u1' ) THEN 1 ELSE 0 END

SQL query to pivot a column using CASE WHEN

I have the following table:
Bank:
name val amount
John 1 2000
Peter 1 1999
Peter 2 1854
John 2 1888
I am trying to write an SQL query to give the following result:
name amountVal1 amountVal2
John 2000 1888
Peter 1999 1854
So far I have this:
SELECT name,
CASE WHEN val = 1 THEN amount ELSE 0 END AS amountVal1,
CASE WHEN val = 2 THEN amount ELSE 0 END AS amountVal2
FROM bank
However, it gives the slightly wrong result:
name amountVal1 amountVal2
John 2000 0
Peter 1999 0
John 0 1888
Peter 0 1854
How can I modify my query to give the correct presentation?
Thanks
SELECT
name,
SUM(CASE WHEN val = 1 THEN amount ELSE 0 END) AS amountVal1,
SUM(CASE WHEN val = 2 THEN amount ELSE 0 END) AS amountVal2
FROM bank GROUP BY name
Looks like you need to join the table on itself. Try this:
select bank1.name, bank1.amount, bank2.amount
from bank bank1
inner join bank bank2 on
bank1.name = bank2.name
and bank1.val = 1
and bank2.val = 2