This is my sample code:
SQL Fiddle
I need it to result like this:
category outlet1 outlet2 outlet3
Sale 70 20 40
Expense 250 130 200
How can I do this?
EDIT: My outlets are not fixed, sorry for not telling this beforehand.
You can solve your particular problem using conditional aggregation:
SELECT c.category,
SUM(CASE WHEN o.outletname = 'Outlet1' THEN t.amt ELSE 0 END) as Outlet1,
SUM(CASE WHEN o.outletname = 'Outlet2' THEN t.amt ELSE 0 END) as Outlet2,
SUM(CASE WHEN o.outletname = 'Outlet3' THEN t.amt ELSE 0 END) as Outlet3
FROM tblcategory c INNER JOIN
tbltran t
ON t.catid = c.id INNER JOIN
tbloutlet o
ON o.id = t.outletid
GROUP BY c.category;
If the outlet names are not fixed, then you need dynamic SQL. The problem cannot be solve using a single SELECT query.
Here with dynamic Outlets http://sqlfiddle.com/#!18/a7b09/25
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(outletname)
from tbloutlet
group by outletname
order by outletname
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT category,' + #cols + ' from
(
SELECT c.category, o.outletname, SUM(t.amt) as amt
FROM tblcategory c
INNER JOIN tbltran t ON t.catid = c.id
INNER JOIN tbloutlet o ON o.id = t.outletid
GROUP BY c.category, o.outletname
) x
pivot
(
sum(amt)
for outletname in (' + #cols + ')
) p '
execute(#query);
you may also use the PIVOT operator
SELECT *
FROM
(
SELECT category, outletname, amt
FROM tblcategory c
INNER JOIN tbltran t ON t.catid = c.id
INNER JOIN tbloutlet o ON o.id = t.outletid
) d
PIVOT
(
SUM(amt)
FOR outletname in ([Outlet1] , [Outlet2] , [Outlet3])
) p
EDIT : below is the Dynamic SQL version
declare #Outlets nvarchar(max),
#SQL nvarchar(max)
select #Outlets = isnull(#Outlets + ',', '') + quotename(outlet)
from outlet
select #SQL = '
SELECT *
FROM
(
SELECT category, outletname, amt
FROM tblcategory c
INNER JOIN tbltran t ON t.catid = c.id
INNER JOIN tbloutlet o ON o.id = t.outletid
) d
PIVOT
(
SUM(amt)
FOR outletname in (' + #Outlets + ')
) p'
print #SQL -- print out for verification
exec sp_executesql #SQL
Related
I have a simple join query for multiple tables that looks like this:
select
b.buyer_id,
v.vendor_id,
r.report_number,
sum(r.amount_fee),
f.fee_description
from buyer b
join vendor v on v.vendor_id = bu.vendor_id
join report r on r.report_num = bu.report_num
join fees f on f.report_num = r.report_num
group by b.buyer_id, v.vendor_id, r.report_number, f.fee_description
Which will show something like this:
But I want it to look like this:
Can you help me how to rewrite my script please?
Thanks alot!
If your fee descriptions are fixed, a simple PIVOT query will do the trick.
SELECT
buyer_id,
vendor_id,
report_number,
[Late Charge],
[Finance Charge],
[Reserve Fee],
[Additional Fee]
FROM
(
select b.buyer_id, v.vendor_id, r.report_number, r.amount_fee As AmountFee, f.fee_description
from buyer b
join vendor v on v.vendor_id = bu.vendor_id
join report r on r.report_num = bu.report_num
join fees f on f.report_num = r.report_num
) As s
PIVOT
(
Sum(AmountFee) FOR fee_description IN ([Late Charge], [Finance Charge], [Reserve Fee], [Additional Fee])
) As P
If the fee descriptions could change, you'll need a dynamic pivot query:
DECLARE #columns nvarchar(max);
SET #columns = STUFF
(
(SELECT DISTINCT N',' + QUOTENAME(fee_description)
FROM fees
ORDER BY fee_description
FOR XML PATH(''), TYPE)
.value('.', 'nvarchar(max)'),
1, 1, N''
);
DECLARE #sql nvarchar(max);
SET #sql = N'SELECT buyer_id, vendor_id, report_number, ' + #columns + N'
FROM
(
select b.buyer_id, v.vendor_id, r.report_number, r.amount_fee As AmountFee, f.fee_description
from buyer b
join vendor v on v.vendor_id = bu.vendor_id
join report r on r.report_num = bu.report_num
join fees f on f.report_num = r.report_num
) As s
PIVOT
(
Sum(AmountFee) FOR fee_description IN (' + #columns + N')
) As P';
EXEC sp_executesql #sql;
I have a table of Customers
Customer ID Name
1 John
2 Lewis
3 Mary
I have another table CustomerRewards
TypeID Description
1 Bronze
2 Silver
3 Gold
4 Platinum
5 AnotherOne
And the final table
RewardID TypeID CustomerID
1 1 1
2 1 1
3 2 1
4 2 2
The customerTypes table is dynamic, many of these types can be added and removed. Basically all I want is the columns to be generated dynamically and a count in each, something like
CustomerName Bronze Silver Gold Platinum AnotherOne total
John 2 1 0 0 0 3
Lewis 0 1 0 0 0 1
Grand TOTAL 2 2 0 0 0 4
The problem like I said it that the types are dynamic and the customers are dynamic so I need the columns to be dynamic depending on the types in the system
I have tagged c# as I need this in a DataGridView
Thanks in advance
You will want to use a PIVOT function for this. If you have a known number of columns, then you can hard-code the values:
select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne]
from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne])
) p;
See SQL Fiddle with Demo.
Now if you have an unknown number of columns, then you can use dynamic SQL to PIVOT:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name,' + #cols + ' from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle With Demo
If you need to include the Total column, then you can use ROLLUP (Static Version Demo):
select name, sum([Bronze]) Bronze, sum([Silver]) Silver,
sum([Gold]) Gold, sum([Platinum]) Platinum, sum([AnotherOne]) AnotherOne
from
(
select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne]
from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne])
) p
) x
group by name with rollup
Dynamic version (Demo):
DECLARE #cols AS NVARCHAR(MAX),
#colsRollup AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsRollup
= STUFF((SELECT ', Sum(' + QUOTENAME(description) + ') as '+ QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'SELECT name, '+ #colsRollup + '
FROM
(
SELECT name,' + #cols + ' from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in (' + #cols + ')
) p
) x1
GROUP BY name with ROLLUP'
execute(#query)
I have following table structure & below is the Query i am executing :-
Following are the tables :-
First Table :-
Second Table :-
SELECT Code, Fname, OTHINC1, OTHINC2
FROM (SELECT a.FieldName
,a.YearlyValue
,b.Code
,b.Fname
FROM [TaxOtherIncome] AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE a.EntryDate = '2014-12-01') x
PIVOT (MAX(YearlyValue) FOR FieldName IN (OTHINC1,OTHINC2)) p
Result i am getting :-
I also want Records from the Second table i mentioned above. So In my final Result Columns SUBFLD36
SUBFLD37 & House_Rent will be added.
As i am new to Pivot, Help me to modify above query to get expected results.
Consider you are inserting the result after your join to a temporary table which is the below
Declare a variable for getting the columns to pivot
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + [FIELD NAME] + ']',
'[' + [FIELD NAME] + ']')
FROM (SELECT DISTINCT [FIELD NAME] FROM #TEMP) PV
ORDER BY [FIELD NAME]
Now pivot it
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT * FROM
(
SELECT * FROM #TEMP
) x
PIVOT
(
MAX([YEARLY VALUE])
FOR [FIELD NAME] IN (' + #cols + ')
) p
'
EXEC SP_EXECUTESQL #query
Click here to view the result
RESULT
You can try this:
SELECT Code, Fname, OTHINC1, OTHINC2, SUBFLD36, SUBFLD37, House_Rent
FROM (SELECT a.FieldName
,a.YearlyValue
,b.Code
,b.Fname
FROM [TaxOtherIncome] AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE a.EntryDate = '2014-12-01'
UNION
SELECT a.FieldName
,a.FieldValue AS YearlyValue
,a.EmployeeCode AS Code
,b.Fname
FROM SecondTable AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE EntryDate = '2014-12-01') x
PIVOT (MAX(YearlyValue) FOR FieldName IN (OTHINC1, OTHINC2, SUBFLD36, SUBFLD37, House_Rent)) p
I am trying to create a pivot table in sql but am having difficulties. Here is my problem: I have a column in my database called 'statusreason', and I need to provide a sum of each statusreason for the past week. My set is as follows:
I need to pivot this table so that it appears like the following:
There are a number of statusreasons that are not represented in the above table, since they did not occur in the past week.
The query used to generate the result set is:
select inv.statusreason
, count(inv.statusreason) as 'StatusCount'
from invoicetbl inv (nolock)
inner join trucktbl tru (nolock) on inv.tru_key = tru.tru_key
where inv.client_key = 123
and inv.createdate > getdate() - 7
group by inv.statusreason
If this isn't enough information, please advise what I could add to improve the question.
Thank you for any assistance you can provide.
Since you want to convert your rows of data into columns, you need to PIVOT the data. This can be done a number of ways.
If you have a limited number of values that you are going to be returning, then you can use an aggregate function with a CASE expression:
select
count(case when statusreason = 181 then 1 end) [181],
count(case when statusreason = 20 then 1 end) [20],
count(case when statusreason = 212 then 1 end) [212],
count(case when statusreason = 232 then 1 end) [232]
from
(
select inv.statusreason
from invoicetbl inv (nolock)
inner join trucktbl tru (nolock)
on inv.tru_key = tru.tru_key
where inv.client_key = 123
and inv.createdate > getdate() - 7
) d;
Or you can use the PIVOT function:
select [181], [20], [212], [232]
from
(
select inv.statusreason
from invoicetbl inv (nolock)
inner join trucktbl tru (nolock)
on inv.tru_key = tru.tru_key
where inv.client_key = 123
and inv.createdate > getdate() - 7
) d
pivot
(
count(statusreason)
for statusreason in ([181], [20], [212], [232])
) p;
If you have an unknown number of values that will be returned, then you will want to look at using dynamic SQL. This creates a sql string that will then be executed.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(statusreasons )
from statusreasontbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
select inv.statusreason
from invoicetbl inv (nolock)
inner join trucktbl tru (nolock)
on inv.tru_key = tru.tru_key
where inv.client_key = 123
and inv.createdate > getdate() - 7
) x
pivot
(
count(statusreason)
for statusreason in (' + #cols + ')
) p '
execute sp_executesql #query;
I have a table of Customers
Customer ID Name
1 John
2 Lewis
3 Mary
I have another table CustomerRewards
TypeID Description
1 Bronze
2 Silver
3 Gold
4 Platinum
5 AnotherOne
And the final table
RewardID TypeID CustomerID
1 1 1
2 1 1
3 2 1
4 2 2
The customerTypes table is dynamic, many of these types can be added and removed. Basically all I want is the columns to be generated dynamically and a count in each, something like
CustomerName Bronze Silver Gold Platinum AnotherOne total
John 2 1 0 0 0 3
Lewis 0 1 0 0 0 1
Grand TOTAL 2 2 0 0 0 4
The problem like I said it that the types are dynamic and the customers are dynamic so I need the columns to be dynamic depending on the types in the system
I have tagged c# as I need this in a DataGridView
Thanks in advance
You will want to use a PIVOT function for this. If you have a known number of columns, then you can hard-code the values:
select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne]
from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne])
) p;
See SQL Fiddle with Demo.
Now if you have an unknown number of columns, then you can use dynamic SQL to PIVOT:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name,' + #cols + ' from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle With Demo
If you need to include the Total column, then you can use ROLLUP (Static Version Demo):
select name, sum([Bronze]) Bronze, sum([Silver]) Silver,
sum([Gold]) Gold, sum([Platinum]) Platinum, sum([AnotherOne]) AnotherOne
from
(
select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne]
from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne])
) p
) x
group by name with rollup
Dynamic version (Demo):
DECLARE #cols AS NVARCHAR(MAX),
#colsRollup AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsRollup
= STUFF((SELECT ', Sum(' + QUOTENAME(description) + ') as '+ QUOTENAME(description)
from customerrewards
group by description, typeid
order by typeid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'SELECT name, '+ #colsRollup + '
FROM
(
SELECT name,' + #cols + ' from
(
select c.name,
cr.description,
r.typeid
from customers c
left join rewards r
on c.id = r.customerid
left join customerrewards cr
on r.typeid = cr.typeid
) x
pivot
(
count(typeid)
for description in (' + #cols + ')
) p
) x1
GROUP BY name with ROLLUP'
execute(#query)