Pivoting two columns with sum [duplicate] - sql

This question already has an answer here:
How to use multiple columns in pivot?
(1 answer)
Closed 3 years ago.
This is my sample Table
**BranchId GroupCode Cash Credit**
1000 AA 10 8644
1000 AA 12 1244
1000 BB 20 7535
1000 CC 30 5633
1001 AA 50 5763
1001 AA 34 2343
1001 BB 60 1000
1001 BB 62 2346
1002 BB 34 1600
1002 CC 68 1700
I want the sample output in this form as shown in the below
**BranchId | AA_Cash | AA_Credit | BB_Cash | BB_Credit | CC_Cash | CC_Credit**
1000 ?
1001
1002
? = I need sum of Cash and Credit in each branches
select * from
(select bid, GroupCode, Cash FROM dueList) as T
PIVOT (sum(Cash) for GroupCode in([AA_Cash],[BB_Cash],[CC_Cash])) PT
This SQL is give output but only cash column, I need add credit column set to the output.
I try using following link
In Sql Server how to Pivot for multiple columns
but in my database there are only 16 branches. Once I try samples in above link it display duplicate lines for branches and lots of null in number area.

You can PIVOT your multi-column data by UNPIVOTing first
For a better visual, run the SELECT within the src subquery
Example
Select *
From (
Select A.BranchID
From YourTable A
Cross Apply ( values (GroupCode+'_Cash' ,Cash)
,(GroupCode+'_Credit',Credit)
) B(Item,Value)
) src
Pivot (sum(Value) for Item in ([AA_Cash],[AA_Credit]
,[BB_Cash],[BB_Credit]
,[CC_Cash],[CC_Credit]
) )pvt
EDIT
On a side-note, it is important to "FEED" your pivot with only the required columns. In your posted example, you included GroupCode. This would generate additional records.

Just use conditional aggregation!
select BranchId,
sum(case when groupcode = 'AA' then cash end) as aa_cash,
sum(case when groupcode = 'AA' then credit end) as aa_credit,
sum(case when groupcode = 'BB' then cash end) as bb_cash,
sum(case when groupcode = 'BB' then credit end) as bb_credit,
sum(case when groupcode = 'CC' then cash end) as cc_cash,
sum(case when groupcode = 'CC' then credit end) as cc_credit
from t
group by BranchId;

Related

Aggregating columns inside a CASE statement

I have a case such that
~id ~from ~to ~label ~weight
100 A B knows 2
100 A B knows 3
100 A B knows 4
But I want only the weight for maximum Date.
How can I modify the below CASE statement such that only 1 entry is there for an ID.
Query:
(
select distinct
CASE WHEN *some-condition* as "~id"
,CASE *some-condition* as "~from"
,CASE *some-condition* as "~to"
,CASE *some-condition* as "~label"
,CASE ??? as "weight"
from
(select
dense_rank() over(partition by t.job_id order by start_time desc) rnk,
t.Date,
t.job_id,
t.start_time,
t.end_time,
t.dep_id,
t.table_name
.....
t.region_id,
from Table1 t
,Tabel2 J
where t.JOB_ID=J.JOB_ID
)
where rnk=1
order by JOB_ID,table_name
)
where "~id" is NOT NULL and "~label" is NOT NULL and "~from" is NOT NULL and "~to" is NOT NULL;
;
Table t
job_id Date table_name ....... dep_id weight
100 2020-10-20 abc 1 2
100 2020-10-20 abc 2 3
100 2020-10-20 abc 3 4
100 2020-10-20 abc 4 10
100 2020-10-19 abc 3 2
Output weight in the result should be corresponding to maximum dep_id.
~id ~from ~to ~label ~weight
100 A B knows 10
It's quite hard to come up with a solution since you didn't state how ~id, ~from, ~to, ~label are calculated. You should be able to achieve your desired output with window functions, i.e. FIRST_VALUE():
...
,CASE *some-condition* as "~label"
,FIRST_VALUE(weight)OVER(ORDER BY dep_id desc) "weight"
...
You may need to add a PARTITION BY clause depending if you want to have the first value overall or depending on some other conditions as well.

Joining two rows into one rows (different column) in oracle

I have table with values like this
ID |Name |Balance |Type |ProductName
1 Abdol 10000 1 RAID100
2 HIVE 5000000 2 RAID100
3 Ade 20000 1 RAID200
4 Koi 30000 1 RAID100
I want to re-arrange the table using select script to:
ProductName | Balance_Type_1 | Balance_Type_2
RAID100 40000 5000000
RAID200 20000 0
I've tried nested case when, but it always create one column with Product-name followed by 0 value besides and repeated.
Thank You
You want aggregation :
select productname,
sum(case when type = 1 then balance else 0 end) as balance_type1,
sum(case when type = 2 then balance else 0 end) as balance_type2
from table t
group by productname;
Run the aggregation query whenever is needed, do not create summary table structure in the database. It will be difficult to manage.
One option would be using pivot provided you database has version 11g+ :
select ProductName ,
sum(nvl(Balance_Type_1,0)) as Balance_Type_1,
sum(nvl(Balance_Type_2,0)) as Balance_Type_2
from t
pivot
(
sum( Balance ) for Type in ( 1 as Balance_Type_1, 2 as Balance_Type_2 )
)
group by ProductName;
Demo

How to pivot on 2 fields

Here is the table I have:
PeriodID RecordID Basis Amount1 Amount2
1 1 IFRS 10 100
1 2 IFRS 20 200
2 1 IFRS 15 150
2 2 IFRS 25 250
1 1 CGAAP 30 300
1 2 CGAAP 40 400
2 1 CGAAP 35 350
2 2 CGAAP 45 450
I would like to pivot on the PeriodID and Basis field so that the result would have following columns:
RecordID
Period1IFRSAmount1
Period2IFRSAmount1
PeriodID1IFRSAmount2
PeriodID2IFRSAmount2
Period1CGAAPAmount1
Period2CGAAPAmount1
PeriodID1CGAAPAmount2
PeriodID2IFRSAmount22
First of all, you need to create the ouput that you need as rows. That is why union part is really important. After you construct your data you can easily use PIVOT.
Following query written in SQL SERVER. It should be similar to other databases as well.
SELECT *
FROM
(
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount1' AS Basis, Amount1 AS Amount
FROM TableName
UNION ALL
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount2' AS Basis, Amount2 AS AMOUNT
FROM TableName
) AS Q
PIVOT (
SUM(Amount)
FOR Basis IN
(
[Period1IFRSAmount1],
[Period2IFRSAmount1],
[Period1IFRSAmount2],
[Period2IFRSAmount2],
[Period1CGAAPAmount1],
[Period2CGAAPAmount1],
[Period1CGAAPAmount2],
[Period2CGAAPAmount2]
)
) AS P

complex paratition sum in postgresql

I have tables as follow:
A deliveries
delveryid clientid deliverydate
1 10 2015-01-01
2 10 2015-02-02
3 11 2015-04-08
B items in deliveris
itemid deliveryid qty status
70 1 5 1
70 1 8 2
70 2 10 1
72 1 12 1
70 3 100 1
I need to add a column to my query that gives me the qty of each part in other deliveris of the same client.
meaning that for given data of client 10 and delivery id 1 I need to show:
itemid qty status qtyOther
70 5 1 10 //itemid 70 exists in delivery 2
70 8 2 10 //itemid 70 exists in delivery 2
72 12 1 0 //itemid 72 doesn't exists in other delivery of client 11
Since I need to add qtyOther to my existing qry i'm trying to avoid using Group By as it's a huge query and if I use SUM in select I will have to group by all items in select.
This is what I have so far:
Select ....., coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) ,0) AS qtyOther
FROM B b
LEFT JOIN A a USING
LEFT JOIN (other tables)
WHERE clientid=10 ....
This query gives me the total sum of qty per itemid for specific clientid, regardless of which delivery it is. How do I change it so it will consider the delivryid? I need something like:
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) FROM B where deliveryid<>b.deliveryid ,0) AS qtyOther
Any suggestions how to do that?
Note: I can NOT change the condition in WHERE.
I think you just want to subtract out the total for the current delivery:
Select .....,
(coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid), 0) -
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid, a.deliveryid), 0)
) as qtyOther

SQL Server : Joining two pivot tables

I'm trying to create join a table with itself. So for example below the table pivots based on the sum of D (Debits) and C (Credits) however I need to join the table with itself to add additional columns displaying count of an "D" entry and "C" plus two more additional columns showing the overall sum and overall count. How do I join the table below to create the additional columns?
Input table
GL_BU GL_Source GL_JE_Type GL_Amount Amount_Prefix
------------------------------------------------------------------
202 Payables Purchase Invoices 1234 C
202 Payables Purchase Invoices 123 D
202 Inventory Inventory 123 C
202 Payables Purchase Invoices 1234 C
Output Table
GL_BU GL_Source GL_JE_Type Amount D Amount C Count D Count C Total Count Total Amount
------------------------------------------------------------------------------------------
202 Spreadsheet XXXXX 1234 123 1 1 2 1357
202 Manual XXXXX 1234 123 2 2 4 1357
202 Manual XXXXX 1234 123 1 1 2 1357
202 Inventory XXXXX 1234 123 4 4 8 1357
202 Sales Order XXXXXX 1234 123 1 1 2 1357
Current Code
SELECT *
FROM
(SELECT
[GL_Business_Unit]
,[GL_Source]
,[GL_JE_Type]
,([GL_Amount])
,[Amount_Prefix]
FROM [03_rdm].[table_2013]) as t
Pivot(SUM([GL_Amount])
FOR [Amount_Prefix] IN (D,C)) AS pvt1
Current code link in SQLFiddle http://sqlfiddle.com/#!3/92369/2
Your sample data doesn't match your desired result so I'm guessing that this is what you need. You could use a PIVOT to get the result, but it seems that this would be much easier to get this using an aggregate function and some conditional logic via a CASE expression:
select
GL_BU,
GL_Source,
GL_JE_Type,
sum(case when Amount_Prefix = 'D' then GL_Amount else 0 end) Amount_D,
sum(case when Amount_Prefix = 'C' then GL_Amount else 0 end) Amount_C,
sum(case when Amount_Prefix = 'D' then 1 else 0 end) Count_D,
sum(case when Amount_Prefix = 'C' then 1 else 0 end) Count_C,
count(*) TotalCount,
sum(GL_Amount) TotalAmount
from table_2013
group by GL_BU, GL_Source, GL_JE_Type;
See SQL Fiddle with Demo