SQL Server : Joining two pivot tables - sql

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

Related

How to bring results from rows into columns with respective values in SQL

I currently have the below results table:
Company ID
External ID
Attribute
Int Value
1
101
Calls
3
1
101
Emails
14
1
101
Accounts
4
2
102
Calls
2
2
102
Emails
17
2
102
Accounts
5
And I would like to transform my query results to show as below:
Company ID
External ID
Calls
Emails
Accounts
1
101
3
14
4
2
102
2
17
5
Is this possible and if so, how would I do this? I'm a new SQL user and can't seem to figure this out :)
This is my current query to get my results:
SELECT
ic.company_id,
ic.external_id,
icca.attribute,
icca.int_value
FROM
intercom_companies AS ic
LEFT JOIN intercom_companies_custom_attributes AS icca
ON ic.company_id = icca.company_id
A pivot query should work here:
SELECT
ic.company_id,
ic.external_id,
MAX(CASE WHEN icca.attribute = 'Calls'
THEN icca.int_value END) AS Calls,
MAX(CASE WHEN icca.attribute = 'Emails'
THEN icca.int_value END) AS Emails,
MAX(CASE WHEN icca.attribute = 'Accounts'
THEN icca.int_value END) AS Accounts
FROM intercom_companies AS ic
LEFT JOIN intercom_companies_custom_attributes AS icca
ON ic.company_id = icca.company_id
GROUP BY
ic.company_id,
ic.external_id;

Find count of transactions and customer where they have purchased one item along with something else SQL

I have a table which has the transaction details of the customer:
Customernum sls unit txn no SKU txn_date
1 10 30 567 903633 2019-02-01 yes
1 20 30 567 123767 2019-02-01 yes
1 50 40 567 126658 2019-03-01 yes
1 10 40 345 773633 2019-02-10 yes
1 12 30 345 965322 2019-02-10
1 10 50 678 838364 2019-02-15 yes
1 10 70 975 983636 2019-02-28 yes
2 11 80 910 903633 2019-02-11
2 11 90 910 566373 2019-02-12 yes
3 11 62 855 678364 2019-02-12
I have another table which has the SKU:
sku Desc
123767 APP
903633 CD
773633 APP
838364 APP
983636 APP
566373 APP
126658 APP
I need to find the transactions from the above transactions which has 903633 in the transaction along with the other SKU from the SKU table and transactions which have more than one of the SKU' from the above table.
So the two questions I am trying to anwer is :
How many transactions included only 1 apparel item along with CD
How many transactions included more than one apparel items with CD.
I have tried the below query but I have had no luck:
select a.Customernum, a.txnno, td.sku,
case when ps.sku is not null
then 'Yes'
else 'No'
end as is_sku,
case when count(b.sku) over (partition by a.txnno) > 0
then 'Yes'
else 'No'
end as has_sku
from table a
left join sku b on b.sku = a.sku;
I am expecting the below result:
Result 1- How many transactions included only 1 apparel item along with CD
customernum txnno unit sls
2 910 80 11
2 910 90 11
1 678 50 10
1 975 70 10
Result 2- How many transactions included more than one apparel items with CD.
customernum txnno unit sls
1 567 30 10
1 567 30 20
1 567 40 50
Use two levels of aggregation. The subquery counts the number of "app"s and "cd"s. The outer filter to just one "cd" (you can use >= if you want at least one) and aggregates by the number of "app"s:
select num_app, count(*) as num_customers
from (select t.customernum,
sum(case when s.desc = 'APP' then 1 else 0 end) as num_app,
sum(case when s.desc = 'CD' then 1 else 0 end) as num_cd
from transactions t join
skus s
on t.sku = s.sku
) c
where num_cd = 1
group by num_app
order by num_app;
You can filter with window functions.
The following query would give you all transactions that involve sku 903633 with exactly one other sku:
select *
from (
select
t.*,
count(*) over(partition by txnno) cnt,
max(case when sku = 903633 then 1 end) has_cd
from mytable t
) t
where has_cd = 1 and cnt = 2
To get the transactions that involve sku 903633 and at least two other skus, you can just change cnt = 2 to cnt > 2.

Pivoting two columns with sum [duplicate]

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;

Conditional Row Deleting in SQL

I have a table that contains 4 columns. I need to remove some of the rows based on the Code and ID columns. A code of 1 initiates the process I'm trying to track and a code of 2 terminates it. I would like to remove all rows for a specific ID when a code of 2 comes after a code of 1 and there is not an additional code 1. For example, my current data set looks like this:
Code Deposit Date ID
1 $100 3/2/2016 5
2 $0 3/1/2016 5
1 $120 2/8/2016 5
1 $120 3/22/2016 4
2 $70 2/8/2016 3
1 $120 1/3/2016 3
2 $0 6/15/2015 2
1 $120 3/22/2016 2
1 $50 8/15/2015 1
2 $200 8/1/2015 1
After I run my script I would like it to look like this:
Code Deposit Date ID
1 $100 3/2/2016 5
2 $0 3/1/2016 5
1 $120 2/8/2016 5
1 $120 3/22/2016 4
1 $50 8/15/2015 1
2 $200 8/1/2015 1
In all I have about 150,000 ID's in my actual table but this is the general idea.
You can get the ids using logic like this:
select t.id
from t
group by t.id
having max(case when code = 2 then date end) > min(case when code = 1 then date end) and -- code 2 after code 1
max(case when code = 2 then date end) > max(case when code = 1 then date end) -- no code 1 after code2
It is then easy enough to incorporate this into a query to get the rest of the details:
select t.*
from t
where t.id not in (select t.id
from t
group by t.id
having max(case when code = 2 then date end) > min(case when code = 1 then date end) and -- code 2 after code 1
max(case when code = 2 then date end) > max(case when code = 1 then date end)
);
The approach I took was to add up the Code per each ID. If it equals 3 exactly, it should be removed.
;WITH keepID as (
Select
ID
,SUM(code) as 'sumCode'
From #testInit
Group by ID
HAVING SUM(code) <> 3
)
Select *
From #testInit
Where ID IN (Select ID from keepID)
Your post showed keeping ID = 1 which does not seem to fit the criteria ? Are you sure you would be keeping ID = 1 ? It only as 2 records with a code of 1 and a code of 2 which adds up to 3 ... thus, remove it.
I just showed the approach in logic ... let me know if you need help with the delete code.
delete from table
where table.id in
(select id from B where A.id=B.id and B.date>A.date
from
(select code,id,max(date),id where code=1 group by id) as A,
(select code ,id,max(date),id where code=2 group by id) as B)
explanation: select code,id,max(date),id where code=1 as A
will fetch data with the highest date for a specific id of code 1
select code ,id,max(date),id where code=2 group by id) as B
will fetch data with the highest date for a specific id of code 2
select id from B where A.id=B.id and B.date>A.date wil select all the ids for which the code 2 date is higher than code 1 date.

SQL Query. limit an update per rows if condition is X and Y for the same ID number

Have the following table tblTrans where
Trans_ID Trans Sequence Trans_PointsEarned Trans_PointsApplied
4452 1 1 1
4452 2 1 1
4452 3 0 1
4462 1 1 1
4462 2 1 1
4462 3 1 1
4462 4 1 1
4462 5 1 1
9101 1 0 1
9101 2 0 1
9101 3 0 1
9101 4 0 1
(useless table doesnt work)
I need to set the following on another field per every customer ID.
So Customer_OverallPoints
4452 = 2 (doesn't count 0's)
4462 = 4 (I want to cap the points to 4 based on the sequence and transID and customerID)
9101 = 0 (dont count 0's).
This needs to be applied to thousands of records based on customerID and TransID where Trans_Sequence is within the same Trans_ID and it only counts the first 4 rows that have the Trans_pointsEarned = 1.
I tried putting a psuedocode together but it just looked ridicilous and I can't even come up with the logic for this.
Thanks
Assuming that TransId is really the customer id, I think the basic logic is just an aggregation:
select t.TransId,
(case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end) as Customer_OverallPoints
from tblTrans t
group by t.TransId;
You can put this into an update statement as:
update customers c
set Customer_OverallPoints = (select (case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end)
from tblTrans t
where t.TransId = c.CustomerId
);