transpose rows to columns in db2 - sql

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

Related

Calculate total donations based on an attribute table

I am trying to get a list of donors who have cumulatively donated $5K+ between two different campaigns. My data is something like this
Attributes table
transactionid
attributevalue
123231
campaign 1
123456
campaing 2
123217
campaign 1
45623
campaing 2
65791
campaing 3
78931
campaign 4
11111
campaign 5
22222
campaing 6
Donations table
transactionid
donationamount
donorid
123231
2000
1233
123456
30000
1456
45623
8000
1233
78931
90
8521
11111
20
1233
22222
68
1456
Donor table
donorid
name
1233
John
1456
Mary
8521
Karl
This is what I tried, but the total I am getting is not right at all.
WITH test AS (
SELECT don.donorid,don.donationamount,a.attributevalue
FROM attributes table a
INNER JOIN donations don ON don.transactionid=a.transactionid
)
SELECT d.donorid,
SUM(CASE WHEN test.attributevalue='campaign 1' OR test.attributevalue='campaign 2'
THEN test.donationamount END) AS campaing_donation,
SUM(test.donationamount) AS total_donations
FROM donortable d
INNER JOIN test ON d.donorid = test.donorid
GROUP BY d.donorid
HAVING SUM(CASE WHEN test.attributevalue = 'campaign 1' OR test.attributevalue = 'campaign 2' THEN test.donationamount END) > 5000
but this is not working. My total donations sum is giving a value that is several times higher than the actual value.
Ideally, the final result would be something like this:
donorid
campaign_amount
totalamount
1233
10000
10020
1456
30000
30068
Select
sum (Donations.donationamount),
donor.donorid,
donor.name
from
Attributes
join Donations on
Donations.transactionid = attributes.transactionid
Join Donor on
donor.donorid = donations.donorid
Where
Attribute.attributevalue in ('campaign 1','campaign 2')
Group by
donor.donorid,
donor.name
create table #transection_tbl(tran_id int,attributevalue varchar(20))
create table #donation_tbl(tran_id int,donation_amount int ,donar_id int)
select donar_id,max(donation_amount) as 'campaing_amount',
sum(donation_amount) as 'totalamount'
from #transection_tbl as t1
inner join #donation_tbl as t2 on t1.tran_id=t2.tran_id
group by donar_id
having COUNT(attributevalue)=2

How to transform my existing table into this specific format using T-SQL?

I am using SQL Server 2014. I have a table T1 (extract shown below):
StayID ProfileID Name ArrivalDate
---------------------------------------
100 200 John 2020-03-15
120 300 Peter 2020-03-10
152 300 Peter 2020-04-25
210 400 Allan 2020-05-12
225 600 Smith 2020-03-28
415 600 Smith 2020-04-15
511 600 Smith 2021-02-20
625 900 Derek 2020-06-14
...
I would like to have the following output using a T-SQL query:
StayID ProfileID Name ArrivalDate StayID2 ArrivalDate2 StayID3 ArrivalDate3
100 200 John 2020-03-15 NULL NULL NULL NULL
120 300 Peter 2020-03-10 152 2020-04-25 NULL NULL
210 400 Allan 2020-05-12 NULL NULL NULL NULL
225 600 Smith 2020-03-28 415 2020-04-15 511 2021-02-20
625 900 Derek 2020-06-14 NULL NULL NULL NULL
The logic here is that data related to a specific ProfileID is to be transformed into the wide format. The StayID column is always unique.
I have been looking into the pivot function but I am not sure if that is the right path to tackle this problem. Any help would be appreciated.
Assuming you know the maximum number of groups you want in the result set, then you can use conditional aggregation:
select profileid, name,
max(case when seqnum = 1 then arrivaldate end) as arrivaldate1,
max(case when seqnum = 1 then stayid end) as stayid1,
max(case when seqnum = 2 then arrivaldate end) as arrivaldate2,
max(case when seqnum = 2 then stayid end) as stayid2,
max(case when seqnum = 3 then arrivaldate end) as arrivaldate3,
max(case when seqnum = 3 then stayid end) as stayid3
from (select t.*,
row_number() over (partition by profileid, name order by arrivaldate) as seqnum
from t
) t
group by profileid, name;
This answers the question that you have asked here. If you do not know the maximum number of groups, then you can use calculate the value in advance and adjust the query or use dynamic SQL.

Transact-SQL Select Query Giving duplicate values

first off, thank you for taking the time to look at this.
I am trying to collect data from 3 tables and make a reference chart that allows the end user to see the stored data.
Basically I have 3 tables for this example:
USERS:
USER_PK USER_ID USER_NAME
1 10000 Bob
2 10001 Sally
3 10003 Joe
4 10004 Susan
SKILL_TYPE:
SKILL_PK SKILL_NAME
11 Point of Sale
22 Digital Sales
33 Customer Service
44 Specialist Support
SKILL_ASSOCIATION:
SKILL_ASSOC_PK SKILL_PK USER_PK START_DATE STOP_DATE Priority
99 11 1 36526 500000 2
88 11 2 36527 500000 3
77 22 1 36526 500000 3
66 33 3 36528 500000 1
55 44 4 36525 500000 1
444 33 4 36525 500000 4
(I know I've probably broken some rules with cataloging this data I did it in SQL Express, however it is only an example and not representative of the real data I am using)
My Select Query Returns an unwanted result with multiple lines for each USER:
Statement:
SELECT USERS.[USER_NAME], USERS.[USER_ID],
(CASE WHEN ST.SKILL_NAME ='Point of Sale' Then SA.[PRIORITY] END) AS 'POS',
(CASE WHEN ST.SKILL_NAME ='Digital Sales' Then SA.[PRIORITY] END) AS 'DS',
(CASE WHEN ST.SKILL_NAME ='Customer Service' Then SA.[PRIORITY] END) AS 'CS',
(CASE WHEN ST.SKILL_NAME ='Specialist Support' Then SA.[PRIORITY] END) AS 'Spec'
FROM USERS
INNER JOIN [dbo].[SKILL_ASSOCIATION] AS SA ON SA.USER_PK = USERS.USER_PK
INNER JOIN SKILL_TYPE AS ST ON ST.SKILL_PK = SA.SKILL_PK
Result:
USER_NAME USER_ID POS DS CS Spec
Bob 10000 2 NULL NULL NULL
Sally 10001 3 NULL NULL NULL
Bob 10000 NULL 3 NULL NULL
Joe 10003 NULL NULL 1 NULL
Susan 10004 NULL NULL NULL 1
Susan 10004 NULL NULL 4 NULL
I've tried using distinct as well with similar results.
Desired Results:
NAME ID POS DS CS Spec
Bob 1 2 3
Sally 2 3
Joe 1
Susan 4 1
I have very limited Query access with this SQL Server and cannot create/modify or delete from it to accomplish my objective.
Any guidance would be much appreciated!
Thanks,
Steven
Your expected output implies that an aggregation by user along with taking the MAX of each of the CASE expressions should work:
SELECT
u.[USER_NAME],
u.[USER_ID],
MAX(CASE WHEN ST.SKILL_NAME = 'Point of Sale' THEN SA.[PRIORITY] END) AS POS,
MAX(CASE WHEN ST.SKILL_NAME = 'Digital Sales' THEN SA.[PRIORITY] END) AS DS,
MAX(CASE WHEN ST.SKILL_NAME = 'Customer Service' THEN SA.[PRIORITY] END) AS CS,
MAX(CASE WHEN ST.SKILL_NAME = 'Specialist Support' THEN SA.[PRIORITY] END) AS Spec
FROM USERS u
INNER JOIN [dbo].[SKILL_ASSOCIATION] AS SA
ON SA.USER_PK = u.USER_PK
INNER JOIN SKILL_TYPE AS ST
ON ST.SKILL_PK = SA.SKILL_PK
GROUP BY
u.[USER_NAME],
u.[USER_ID];

SQL pivot unpivot query

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.

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