sqlserver records need to come horizontly - sql

I have table structure below,
Table Name: Customer
Cust_id Cust_Name
------------------------
101 John
102 Peter
Table Name: Loan_Details
Id LoanName Cust_Id Amt
-----------------------------------------
1 PersonalLoan 101 2L
2 PersonalLoan 101 3L
3 HomeLoan 101 10L
Table Name: Product
Id Cust_Id ProductName Cost
-----------------------------------------
1 101 Product1 1000
2 101 Product1 2000
3 101 Product1 3000
I need result horizontly in below structure, is it possble?
Cust_Id Cust_Name PersonalLoan Amt HomeLoan Amt ProductName Cost
--------------------------------------------------------------------------------
101 John PersonalLoan 2L HomeLoan 10L Product1 1000
101 John PersonalLoan 3L NULL NULL Product1 2000
101 John NULL NULL NULL NULL Product1 3000

You can try this query.
If you want to list "Peter" too, just change INNER JOIN to LEFT JOIN in the CusPrd subquery.
DECLARE #Customer TABLE (Cust_id VARCHAR(10), Cust_Name VARCHAR(20))
INSERT INTO #Customer
VALUES
('101','John'),
('102','Peter')
DECLARE #Loan_Details TABLE (Id INT, LoanName VARCHAR(20), Cust_Id VARCHAR(10), Amt VARCHAR(10))
INSERT INTO #Loan_Details
VALUES
(1,'PersonalLoan','101','2L'),
(2,'PersonalLoan','101','3L'),
(3,'HomeLoan','101','10L')
DECLARE #Product TABLE (Id INT, Cust_Id VARCHAR(10), ProductName VARCHAR(20), Cost INT)
INSERT INTO #Product
VALUES
(1,'101','Product1',1000),
(2,'101','Product1',2000),
(3,'101','Product1',3000)
;WITH Loan AS
(
SELECT *,
RN = ROW_NUMBER() OVER (PARTITION BY LoanName ORDER BY Id)
FROM #Loan_Details
),
CusPrd AS
(
SELECT
C.Cust_id,
C.Cust_Name,
P.ProductName,
P.Cost,
P.Id,
RN = ROW_NUMBER() OVER (PARTITION BY C.Cust_id ORDER BY P.Id)
FROM
#Customer C
INNER JOIN #Product P ON C.Cust_id = P.Cust_Id
)
SELECT C.Cust_id, C.Cust_Name, PL.LoanName [PersonalLoan], PL.Amt, HL.LoanName [HomeLoan], HL.Amt, C.ProductName, C.Cost
FROM
CusPrd C
LEFT JOIN Loan PL ON PL.Cust_Id = C.Cust_id AND PL.LoanName ='PersonalLoan' AND C.RN = PL.RN
LEFT JOIN Loan HL ON HL.Cust_Id = C.Cust_id AND HL.LoanName ='HomeLoan' AND PL.RN = HL.RN AND C.RN = PL.RN
Result:
Cust_id Cust_Name PersonalLoan Amt HomeLoan Amt ProductName Cost
---------- -------------------- -------------------- ---------- -------------------- ---------- -------------------- -----------
101 John PersonalLoan 2L HomeLoan 10L Product1 1000
101 John PersonalLoan 3L NULL NULL Product1 2000
101 John NULL NULL NULL NULL Product1 3000

select * from
(select c.Cust_id,Cust_Name,ld.LoanName as Loan,Amt,ProductName,Cost
from Customer c left join Product p on p.Cust_id=c.Cust_id
left join Loan_Details ld on ld.Cust_id = c.Cust_id) as MTable
PIVOT
(
SUM(Amt) for Loan in ([HomeLoan],[PersonalLoan])
) as PTable
Use this it will give you what you want the result is something like this
Cust_id Cust_Name ProductName Cost HomeLoan PersonalLoan
----------- -------------------- -------------------- ----------- ----------- ------------
101 John Product1 1000 10 5
101 John Product12 2000 10 5
101 John Product2 3000 10 5
102 Peter NULL NULL NULL NULL

Related

get multiple column from both table by joining a table on the basis of other max table column

1) vendor table
--------------------------------------------
VENDid VENDname
--- -----
1 ABC
2 XYZ
3 WXY
2)purchase table
---------------------------------------------
VENDid Purchasedate
------ ------------
1 12-01-2012
1 10-11-2013
2 22-02-2014
2 11-04-2014
3 10-05-2014
3 11-06-2014
1 14-06-2014
output(list all rows of vendor table and only max(purchasedate) from purchase table)
---------------------------------------------
VENDid VENDname PurchaseDate
------- -------- -------------
1 ABC 14-06-2014
2 XYZ 11-04-2014
3 WXY 11-06-2014
i got some queries like to solve previous problem-
SELECT v.VendID, VendName, Max(PurchaseDate)
FROM vendor v
INNER JOIN purchase p
ON v.VendID = p.VendID
Group By v.VendID, VendName
select VENDid, VENDname,
(select top 1 purchaseDate from purchase p
where p.VENDid=v.VENDid order by purchaseDate desc) as 'Purchase date'
from Vendor v
Que. If i will add some more column in purchase table like -
2)purchase table
------------------------------------------
VENDid Purchasedate amount_paid
------ ------------ ------------
1 12-01-2012 10000
1 10-11-2013 20000
2 22-02-2014 15000
2 11-04-2014 30000
3 10-05-2014 80000
3 11-06-2014 17000
1 14-06-2014 28000
and i want amount_paid along with previous output like-
---------------------------------------------
VENDid VENDname PurchaseDate amount_paid
------- -------- ------------- -------------
1 ABC 14-06-2014 28000
2 XYZ 11-04-2014 30000
3 WXY 11-06-2014 17000
then what will be query..
You appear to be using SQL Server. If so, you can use cross apply:
select v.VENDid, v.VENDname, p.PurchaseDate, p.Amount_Paid
from Vendor v cross apply
(select top 1 p.*
from purchase p
where p.VENDid = v.VENDid
order by p.purchaseDate desc
) p ;

SQL Server : take 1 to many record set and make 1 record per id

I need some help. I need to take the data from these 3 tables and create an output that looks like below. The plan_name_x and pending_tallyx columns are derived to make one line per claim id. Each claim id can be associated to up to 3 plans and I want to show each plan and tally amounts in one record. What is the best way to do this?
Thanks for any ideas. :)
Output result set needed:
claim_id ac_name plan_name_1 pending_tally1 plan_name_2 Pending_tally2 plan_name_3 pending_tally3
-------- ------- ----------- -------------- ----------- -------------- ----------- --------------
1234 abc cooks delux_prime 22 prime_express 23 standard_prime 2
2341 zzz bakers delpux_prime 22 standard_prime 2 NULL NULL
3412 azb pasta's prime_express 23 NULL NULL NULL NULL
SQL Server 2005 table to use for the above result set:
company_claims
claim_id ac_name
1234 abc cooks
2341 zzz bakers
3412 azb pasta's
claim_plans
claim_id plan_id plan_name
1234 101 delux_prime
1234 102 Prime_express
1234 103 standard_prime
2341 101 delux_prime
2341 103 standard_prime
3412 102 Prime_express
Pending_amounts
claim_id plan_id Pending_tally
1234 101 22
1234 102 23
1234 103 2
2341 101 22
2341 103 2
3412 102 23
If you know that 3 is always the max amount of plans then some left joins will work fine:
select c.claim_id, c.ac_name,
cp1.plan_name as plan_name_1, pa1.pending_tally as pending_tally1,
cp2.plan_name as plan_name_2, pa2.pending_tally as pending_tally2,
cp3.plan_name as plan_name_3, pa3.pending_tally as pending_tally3,
from company_claims c
left join claim_plans cp1 on c.claim_id = cp1.claim_id and cp1.planid = 101
left join claim_plans cp2 on c.claim_id = cp2.claim_id and cp2.planid = 102
left join claim_plans cp3 on c.claim_id = cp3.claim_id and cp3.planid = 103
left join pending_amounts pa1 on cp1.claim_id = pa1.claimid and cp1.planid = pa1.plainid
left join pending_amounts pa2 on cp2.claim_id = pa2.claimid and cp2.planid = pa2.plainid
left join pending_amounts pa3 on cp3.claim_id = pa3.claimid and cp3.planid = pa3.plainid
I would first join all your data so that you get the relevant columns: claim_id, ac_name, plan_name, pending tally.
Then I would add transform this to get plan name and plan tally on different rows, with a label tying them together.
Then it should be easy to pivot.
I would tie these together with common table expressions.
Here's the query:
with X as (
select cc.*, cp.plan_name, pa.pending_tally,
rank() over (partition by cc.claim_id order by plan_name) as r
from company_claims cc
join claim_plans cp on cp.claim_id = cc.claim_id
join pending_amounts pa on pa.claim_id = cp.claim_id
and pa.plan_id = cp.plan_id
), P as (
select
X.claim_id,
x.ac_name,
x.plan_name as value,
'plan_name_' + cast(r as varchar(max)) as label
from x
union all
select
X.claim_id,
x.ac_name,
cast(x.pending_tally as varchar(max)) as value,
'pending_tally' + cast(r as varchar(max)) as label
from x
)
select claim_id, ac_name, [plan_name_1], [pending_tally1],[plan_name_2], [pending_tally2],[plan_name_3], [pending_tally3]
from (select * from P) p
pivot (
max(value)
for label in ([plan_name_1], [pending_tally1],[plan_name_2], [pending_tally2],[plan_name_3], [pending_tally3])
) as pvt
order by pvt.claim_id, ac_name
Here's a fiddle showing it in action: http://sqlfiddle.com/#!3/68f62/10

how do I use Pivot in Sql Server?

I have a table that stores the data as follows:
username status
user1 HT
user2 EC
user1 PR
user1 EC
user2 HT
I need result something like this
username HT EC PR GrandTotal
user1 1 1 1 3
user2 1 1 0 2
Total 2 2 1 5
please anybody help me. Thanks in advance
It is simple when Status values are fixed.
select
username,
sum(case when status='HT' then 1 else 0 end) as HT,
sum(case when status='EC' then 1 else 0 end) as EC,
sum(case when status='PR' then 1 else 0 end) as PR,
count(*) as total
from
table
group by
username
WITH ROLLUP
If they are dynamic, you need to use http://beyondrelational.com/modules/2/blogs/70/posts/10840/dynamic-pivot-in-sql-server-2005.aspx
USE AdventureWorks
GO
-- Creating Test Table
CREATE TABLE Product(Cust VARCHAR(25), Product VARCHAR(20), QTY INT)
GO
-- Inserting Data into Table
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',2)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','SODA',6)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','MILK',1)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','BEER',12)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','MILK',3)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','BEER',24)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',3)
GO
-- Selecting and checking entires in table
SELECT *
FROM Product
GO
-- Pivot Table ordered by PRODUCT
SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT
GO
-- Pivot Table ordered by CUST
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt
ORDER BY CUST
GO
-- Unpivot Table ordered by CUST
SELECT CUST, PRODUCT, QTY
FROM
(
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT
( SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt) p
UNPIVOT
(QTY FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)
) AS Unpvt
GO
-- Clean up database
DROP TABLE Product
GO
ResultSet:
-- Selecting and checking entires in table
Cust Product QTY
------------------------- -------------------- -----------
KATE VEG 2
KATE SODA 6
KATE MILK 1
KATE BEER 12
FRED MILK 3
FRED BEER 24
KATE VEG 3
-- Pivot Table ordered by PRODUCT
PRODUCT FRED KATE
-------------------- ----------- -----------
BEER 24 12
MILK 3 1
SODA NULL 6
VEG NULL 5
-- Pivot Table ordered by CUST
CUST VEG SODA MILK BEER CHIPS
------------------------- ----------- ----------- ----------- ----------- -----------
FRED NULL NULL 3 24 NULL
KATE 5 6 1 12 NULL
-- Unpivot Table ordered by CUST
CUST PRODUCT QTY
------------------------- -------- -----------
FRED MILK 3
FRED BEER 24
KATE VEG 5
KATE SODA 6
KATE MILK 1
KATE BEER 12 12
Reference:
http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/

How to achieve right result from a table list

The goal is to retrieve this result below:
MaterialNumber ExpiryDate Quantity
-------------- ---------- --------
11111 10-12-2011 50
11111 10-18-2011 100
11111 01-15-2012 500
22222 11-18-2011 0
22222 05-01-2012 200
33333 12-17-2011 200
33333 04-01-2012 -275
The problem is that I don't know now how to achieve this result based on my existing code further below.
I also having problem with calculation.
SupplyID MaterialNumber ExpiryDate Quantity
-------- -------------- ---------- --------
1 11111 10-12-2011 100
2 11111 10-18-2011 700
3 11111 01-15-2012 500
4 22222 11-18-2011 250
5 22222 05-01-2012 475
6 33333 12-17-2011 200
7 33333 04-01-2012 300
RequestID MaterialNumber RequiredDate Quantity
--------- -------------- ------------ --------
1 11111 10-01-2011 50
2 11111 10-14-2011 600
3 22222 10-17-2011 400
4 22222 04-02-2012 125
5 33333 12-22-2011 175
6 33333 01-10-2012 400
CREATE TABLE TC74_Supply
(
SupplyID INT IDENTITY,
MaterialNumber VARCHAR(5),
ExpiryDate DATE,
Quantity INT
)
GO
INSERT INTO TC74_Supply(MaterialNumber,ExpiryDate,Quantity)
SELECT '11111','10-12-2011',100 UNION ALL
SELECT '11111','10-18-2011',700 UNION ALL
SELECT '11111','01-15-2012',500 UNION ALL
SELECT '22222','11-18-2011',250 UNION ALL
SELECT '22222','05-01-2012',475 UNION ALL
SELECT '33333','12-17-2011',200 UNION ALL
SELECT '33333','04-01-2012',300
CREATE TABLE TC74_SupplyRequest(
RequestID INT IDENTITY,
MaterialNumber VARCHAR(5),
RequiredDate DATE,
Quantity INT
)
GO
INSERT INTO TC74_SupplyRequest(MaterialNumber,RequiredDate,Quantity)
SELECT '11111','10-01-2011',50 UNION ALL
SELECT '11111','10-14-2011',600 UNION ALL
SELECT '22222','10-17-2011',400 UNION ALL
SELECT '22222','04-02-2012',125 UNION ALL
SELECT '33333','12-22-2011',175 UNION ALL
SELECT '33333','01-10-2012',400
My source code below that is not completed yet
SELECT
a.SupplyID,
a.MaterialNumber,
a.ExpiryDate,
a.Quantity,
a.test1,
godis =(SELECT top 1 a.Quantity - c.Quantity
FROM (SELECT
b.RequestID,
b.MaterialNumber,
b.RequiredDate,
b.Quantity,
test2 = DENSE_RANK() OVER(PARTITION BY b.MaterialNumber ORDER BY b.RequestID)
FROM TC74_SupplyRequest b) c
WHERE MaterialNumber = c.MaterialNumber AND a.test1 = c.test2),
a.lll
FROM
(
SELECT
SupplyID,
MaterialNumber,
ExpiryDate,
Quantity,
test1 = DENSE_RANK() OVER(PARTITION BY MaterialNumber ORDER BY SupplyID),
lll = 321
FROM
TC74_Supply
) a
So you have some quickly evaporating stuff on your hands? If you need to sum requests in period starting at last expiry date to current expiry date, you might use this:
select *, Quantity - isnull(Demand, 0) Vasted
from TC74_Supply
outer Apply
(
select sum (Quantity) Demand
from TC74_SupplyRequest
where TC74_Supply.MaterialNumber = TC74_SupplyRequest.MaterialNumber
and TC74_Supply.ExpiryDate >= TC74_SupplyRequest.RequiredDate
and TC74_SupplyRequest.RequiredDate >=
(select isnull (max(a.ExpiryDate),
(select min(RequiredDate) from TC74_SupplyRequest))
from TC74_Supply a
where a.MaterialNumber = TC74_Supply.MaterialNumber
and a.ExpiryDate < TC74_Supply.ExpiryDate)
) a
I'm curious about '22222'. My numbers don't match yours, and I couldn't find a scenario where I would get exact numbers. The question that I'm trying to ask is: do you have some total of material that expires at certain dates, so that request might be served by few entries in Supply table?

How to Join three tables

I have 3 tables : Orders, Customers and Suppliers
Structure and Data:
Orders
================================
OrdNo, OrdDt, OrdType, CSID
--------------------------------
1 01/04/2011 C 2
2 01/04/2011 S 1
--------------------------------
Customers
----------
CID, CName
----------
1 John
2 Boby
----------
Suppliers
=========
SID, SName
----------
1 Tony
2 Mohan
----------
If OrdTYpe = "C" then pick data from Customers table for CSID = CID
If OrdTYpe = "S" then pick data from Suppliers table for CSID = SID
How to list the records like
--------------------------------------
OrdNo, OrdDt, OrdType, CSID CSName
--------------------------------------
1 01/04/2011 C 2 Boby
2 01/04/2011 S 1 Tony
--------------------------------------
Does this get what you want?
SELECT ordno, orddt, ordtype, csid,
COALESCE( c.name, s.name ) csname
FROM orders o
LEFT JOIN customer c ON o.ordtype='C' AND c.cid = o.csid
LEFT JOIN suppliers s ON o.ordtype='S' AND c.sid = o.csid
Another possibility, at least in Oracle, would be:
SELECT ordno, orddt, ordtype, csid,
CASE WHEN ordtype='C' THEN (SELECT name FROM customer WHERE cid = csid)
WHEN ordtype='S' THEN (SELECT name FROM suppliers WHERE sid = csid)
END csname
FROM orders;
Martin has a good point. I'm no pro, but I would suggest making an intermediate table that will allow you to keep customers and suppliers separate, yet still pull from a common set of id's
Orders
========================
OrdNo, OrdDt, CSID
------------------------
1 01/04/2011 2
2 01/04/2011 1
-------------------------
ClientIDs
---
ID
---
1
2
3
4
---
Customers
----------
CID, CName
----------
1 John
3 Boby
----------
Suppliers
=========
SID, SName
----------
2 Tony
4 Mohan
----------
That way you end up with something like this:
-------------------------------
OrdNo, OrdDt, CSID CSName
-------------------------------
1 01/04/2011 2 Tony
2 01/04/2011 1 John
-------------------------------
and by back tracking up through the (now) unique ID you will be able to tell if it is a customer, or supplier... also I'm pretty sure your SQL will run faster with this route (don't hold me to it though). If you like this idea, I could look into SQL to back it.
SELECT o.[OrdNo], o.[OrdDt], o.[OrdType], o.[CSID],
CASE WHEN o.[OrdType] = 'C'
THEN c.[CName]
ELSE s.[SName]
END as [CSName]
FROM Orders AS o
LEFT JOIN Customers AS c
ON o.[CSID] = c.[CID]
LEFT JOIN Suppliers AS s
ON o.[CSID] = s.[SID]