how to remove null values from an sql pivot? - sql

How can i replace the null values with zero in the sql pivot table?
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Ref,role_name,offer_id, ' + #cols + ' from
(
select*
from #cover2
) x
pivot
(
SUM(cover_earning_Count)
for [offer_cover] in (' + #cols + ')
) p '
execute(#query)
Output:
Ref role_name offer_id 10000 104000 112000
43132_43282 Call Center 1 1 NULL NULL
43132_43282 Others 1 2 NULL NULL
43160_43282 Call Center 1 6 NULL 1
43160_43282 Others 1 NULL 1 NULL
43191_43282 Call Center 1 7 NULL NULL
43191_43282 Others 1 3 1 1
43221_43282 Call Center 1 4 1 1
43221_43282 Others 1 2 NULL NULL
Cover2 Table
Ref YEAR MONTH Role_name offer_cover offer_id Cover_Earning_Count CONF_DATE Curr_date
43132_43282 2018 2 Call Center 2000 1 5 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 4000 1 8 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 6000 1 2 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 8000 1 4 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 10000 1 1 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 12000 1 6 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 14000 1 2 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 16000 1 4 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 20000 1 6 2/1/2018 7/1/2018
43132_43282 2018 2 Call Center 24000 1 5 2/1/2018 7/1/2018

as i have mention earlier in my comments, you need 2 #cols, one for the select and another for the pivot
DECLARE #cols AS NVARCHAR(MAX), -- for pivot
#cols2 AS NVARCHAR(MAX), -- for select
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
-- this is for the SELECT
SET #cols2 = STUFF((SELECT distinct ',' + 'ISNULL(' + QUOTENAME(c.[Offer_cover]) + ', 0) ' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Ref,role_name,offer_id, ' + #cols2 + ' from
(
select *
from #cover2
) x
pivot
(
SUM(cover_earning_Count)
for [Offer_cover] in (' + #cols + ')
) p'
-- do a print to verify the query
print #query

Try using ISNULL
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[Offer_cover])
FROM #Table1 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Ref,role_name,offer_id, ' + isnull(#cols,0) + ' from
(
select*
from #Table1
) x
pivot
(
SUM(cover_earning_Count)
for [offer_cover] in (' + #cols + ')
) p '
execute(#query)

Related

SQL Server 2016 Pivot

I have one question regarding sql (MS SQL 2016) and pivot functionality.
First let me explain about the data structure.
Examples of tbl_Preise. There are several prices (Preis) for each area (Gebiet_von, Gebiet_bis) in relays (StaffelNr). All connected to the same freight (Fracht_id). There can be a different number of relays for each freight. All of these relays repeat for each area, so i.e. there is one price for relay 1 in area 1800 - 1899, but there is another price for relay 1 for area 1900 - 1999.
This is how the table tbl_Preise looks:
autoID Fracht_id Gebiet_von Gebiet_bis Zielland_Nr StaffelNr Preis Mindestpreis Mautkosten
16933 4 1800 1899 4 1 22,6481 0,00 0,00
16934 4 1800 1899 4 2 37,0843 0,00 0,00
16935 4 1800 1899 4 3 54,9713 0,00 0,00
16936 4 1900 1999 4 1 23,4062 0,00 0,00
16937 4 1900 1999 4 2 84,4444 0,00 0,00
Now I have another table tbl_Fracht_Staffeln where the quantity of the relay is saved.
This table looks like:
id fracht_id staffelNr menge
18 4 1 50
19 4 2 100
20 4 3 150
21 4 4 200
Now I want to combine these data, which can vary through different number of relays to each freight.
I have done this via this query:
DECLARE #cols AS NVARCHAR(MAX),#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(staffelNr)
from tbl_Preise (nolock)
where fracht_id = #freightId
group by staffelNr
order by StaffelNr
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'
SELECT
Bezeichnung,
fracht_id,
gebiet_von,
gebiet_bis,
' + #cols + N'
from
(
select
l.Bezeichnung as Bezeichnung,
Zielland_Nr,
tbl_Preise.fracht_id,
gebiet_von,
gebiet_bis,
preis,
tbl_Preise.staffelNr as staffelNr
from
tbl_Preise (nolock)
left join
[dbo].[vw_Laender] l on tbl_Preise.Zielland_Nr = l.[Nummer]
where
tbl_Preise.Fracht_id = ' + cast(#freightId as nvarchar(100)) + '
) x
pivot
(
max(preis)
for staffelNr in (' + #cols + N')
) p
order by
gebiet_von, gebiet_bis'
exec sp_executesql #query;
This query gives me this result:
Bezeichnung fracht_id gebiet_von gebiet_bis 1 2 3 4 5 6
Germany 4 01800 01899 NULL NULL NULL NULL NULL NULL
Germany 4 06400 06499 NULL NULL NULL NULL NULL NULL
Germany 4 1800 1899 22,6481 37,0843 54,9713 64,4062 84,4444 94,6546
Germany 4 20500 20599 17,9088 27,3983 40,8845 46,7485 61,4905 67,835
Germany 4 21200 21299 17,9088 27,3983 40,8845 46,7485 61,4905 67,835
Germany 4 21500 21599 17,9088 27,3983 40,8845 46,7485 61,4905 67,835
Don't look exactly on the prices and the area codes. I've changed some in my example of tbl_Preise to make the relation and sense more clear.
So far so good. But now, as you can see, I have the staffelNr (1,2,3,4,...) as Header in my table.
I need there the column menge of table tbl_Fracht_Staffeln instead.
I tried already some joins and other stuff, but all did not work, because I have found no way to connect the column names (1,2,3,4...) to the table tbl_Fracht_Staffeln. Is there any way to achieve this?
Thank you very much in advance for help!
To do this you need to play with column header 2 times -
DECLARE #cols AS NVARCHAR(MAX),#query AS NVARCHAR(MAX) , #freightId as int , #cols1 AS NVARCHAR(MAX)
select #freightId = 4
select #cols = STUFF((SELECT ',' + QUOTENAME(t1.staffelNr) + ' as ' + QUOTENAME(t2.menge )
from tbl_Preise t1 (nolock)
join tbl_Fracht_Staffeln t2(nolock)
on t1.fracht_id = t2.fracht_id and t1.staffelNr = t2.staffelNr
where t1.fracht_id = #freightId
group by t1.staffelNr , t2.menge
order by t1.StaffelNr
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols1 = STUFF((SELECT ',' + QUOTENAME(staffelNr)
from tbl_Preise (nolock)
where fracht_id = #freightId
group by staffelNr
order by StaffelNr
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'
SELECT
fracht_id,
gebiet_von,
gebiet_bis,
' + #cols + N'
from
(
select
Zielland_Nr,
tbl_Preise.fracht_id,
gebiet_von,
gebiet_bis,
preis,
tbl_Preise.staffelNr as staffelNr
from
tbl_Preise (nolock)
where
tbl_Preise.Fracht_id = ' + cast(#freightId as nvarchar(100)) + '
) x
pivot
(
max(preis)
for staffelNr in (' + #cols1 + N')
) p
order by
gebiet_von, gebiet_bis'
print #query
exec sp_executesql #query;

how to make a dynamic sql pivot

I have a select statement with the following
select country,city,school,class,quantity from tableA
I want the pivot to be based on class like in the below table:
country City School ClassA ClassB ClassC ClassD
XXX AAA SCH01 37 37 39 37
XXX BBB SCH02 12 12 1 12
XXX BBB SCH03 6 6 9 6
XXX DDD SCH04 1 1 1 1
YYY ABC SCH05 1 1 1 1
YYY CDE SCH06 1 1 1 1
YYY EDY SCH07 1 1 1 1
YYY ZER SCH08 1 1 1 1
SSS GFY SCH09 1 1 1 1
SSS AHY SCH10 1 1 1 1
MS SQL SERVER:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([class])
from [table-name]
group by [class]
order by [class]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [country], [city], [school],' + #cols + ' from
(
select [country], [city], [school],[class],[quantity]
from [table-name]
) x
pivot
(
sum([quantity])
for [class] in (' + #cols + ')
) p '
execute(#query);

Select row to column SQL

I didn't meet row to column before, can you help me?
This is example of my source.
And I want to select from:
Id Project ID Date Hour
-------------------------------
1 Project-1 1/1/2010 10
2 Project-1 1/2/2010 2
3 Project-1 1/3/2010 3
4 Project-1 1/4/2010 5
5 Project-2 1/1/2010 3
6 Project-2 1/2/2010 4
7 Project-2 1/3/2010 2
8 Project-2 1/4/2010 7
9 Project-3 1/1/2010 5
10 Project-3 1/2/2010 6
11 Project-3 1/3/2010 4
.
.
.
to
Project ID 1/1/2010 1/2/2010 1/3/2010 1/4/2010 ...
----------------------------------------------------------------
Project-1 10 2 3 5
Project-2 3 4 2 7
Project-3 5 6 4
Please help me.
UPDATE:
This is my solution.
--============== Create stored procedure ============
if exists(select * from sys.procedures where name='usp_ProjectFollow')
drop procedure usp_ProjectFollow
go
create proc usp_ProjectFollow
as
begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Declare #ParamDefinition AS NVarchar(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME([Date])
FROM MyTable
group by [Date]
order by [Date]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT id, ProjectName, ProjectCode, ' + #cols +
' FROM MyTable
pivot
(
sum(Hour)
for Date in (' + #cols + ')
) p '
--print #query
execute sp_Executesql #query
end
go
hope it's will help someone need.
A static solution is using this type of query:
SELECT
ProjectID,
SUM(CASE WHEN Date = '1/1/2010' THEN Hour ELSE 0 END) As '1/1/2010',
SUM(CASE WHEN Date = '1/2/2010' THEN Hour ELSE 0 END) As '1/2/2010',
SUM(CASE WHEN Date = '1/3/2010' THEN Hour ELSE 0 END) As '1/3/2010',
SUM(CASE WHEN Date = '1/4/2010' THEN Hour ELSE 0 END) As '1/4/2010',
...
FROM
yourTable
GROUP BY
ProjectID;
For using a dynamic solution you need to use dynamic SQL like this:
Declare #SQL nvarchar(MAX)
SELECT #SQL = ISNULL(#SQL, 'SELECT ProjectID') + ', SUM(CASE WHEN Date = ''' + [Date] + ''' THEN [Hour] ELSE 0 END) As [' + [Date] + ']'
FROM #t
GROUP BY [Date]
SELECT #SQL = #SQL + ' FROM yourTable GROUP BY ProjectID;'
EXEC(#SQL)

SQL Multiple dynamic queries to one query

I am working in a SQL Server 2008 environment with SQL Server Management Studio 2012.
I have written 3 separate queries
QUERY 1
SQL query SUMS all the STOCK ON HAND from an Inventories table
SELECT StockCode,
Sum(QtyOnHand) AS 'SOH'
FROM InvWarehouse
WHERE StockCode NOT LIKE '%DEM%' AND StockCode NOT LIKE '%REF%' AND StockCode NOT LIKE 'Z%'
GROUP BY InvWarehouse.StockCode
QUERY 2
This query looks at future orders from a Purchase Orders Table and dynamically returns the next/following 12 months
DECLARE
#cols AS NVARCHAR(MAX),
#cols1 AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#cols3 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(YearMonth)
FROM
-- Selecting Using the Destinct --
(SELECT DISTINCT CAST(YEAR([OrderDueDate]) AS NVARCHAR(4)) + RIGHT('00' + CAST(MONTH([OrderDueDate]) AS NVARCHAR(2)),2) AS YearMonth
FROM PorMasterHdr
JOIN PorMasterDetail
ON PorMasterDetail.PurchaseOrder = PorMasterHdr.PurchaseOrder
WHERE DATEDIFF(MONTH, OrderDueDate, DATEADD(m,12,GETDATE())) <= 12 ) sub
ORDER BY YearMonth
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,''),
#cols2 = STUFF((SELECT ',ISNULL(' + QUOTENAME(YearMonth) + ',0) AS ' + QUOTENAME(YearMonth)
FROM
-- Selecting Using the Destinct --
(SELECT DISTINCT CAST(YEAR([OrderDueDate]) AS NVARCHAR(4)) + RIGHT('00' + CAST(MONTH([OrderDueDate]) AS NVARCHAR(2)),2) AS YearMonth
FROM PorMasterHdr
JOIN PorMasterDetail
ON PorMasterDetail.PurchaseOrder = PorMasterHdr.PurchaseOrder
WHERE DATEDIFF(MONTH, OrderDueDate, DATEADD(m,12,GETDATE())) <= 12) sub
ORDER BY YearMonth
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = '
SELECT MStockCode, ' + #cols2 + '
FROM (
SELECT MStockCode,
MOrderQty,
CAST(YEAR([OrderDueDate]) AS NVARCHAR(4))+RIGHT(''00''+CAST(MONTH([OrderDueDate]) AS NVARCHAR(2)),2) AS YearMonth
FROM PorMasterHdr
JOIN PorMasterDetail
ON PorMasterDetail.PurchaseOrder = PorMasterHdr.PurchaseOrder
WHERE MStockCode NOT LIKE ''%DEM%'' AND MStockCode NOT LIKE ''%REF%'' AND MStockCode NOT LIKE ''Z%''
) AS X
PIVOT (
SUM(MOrderQty)
FOR YearMonth in (' + #cols + ')
) AS PT'
EXECUTE (#query)
QUERY 3
This query looks at the past 12 month of sales data from a Sales table and dynamically returns the last/previous 12 months
DECLARE
#cols AS NVARCHAR(MAX),
#cols1 AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#cols3 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(YearMonth)
FROM
-- Selecting Using the Destinct --
(SELECT DISTINCT CAST([TrnYear] AS NVARCHAR(4)) + RIGHT('00' + CAST([TrnMonth] AS NVARCHAR(2)),2) AS YearMonth
FROM ArTrnDetail
WHERE DATEDIFF(MONTH, InvoiceDate, GETDATE()) <= 12 ) sub
ORDER BY YearMonth
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,''),
#cols2 = STUFF((SELECT ',ISNULL(' + QUOTENAME(YearMonth) + ',0) AS ' + QUOTENAME(YearMonth)
FROM
-- Selecting Using the Destinct --
(SELECT DISTINCT CAST([TrnYear] AS NVARCHAR(4)) + RIGHT('00' + CAST([TrnMonth] AS NVARCHAR(2)),2) AS YearMonth
FROM ArTrnDetail
WHERE DATEDIFF(MONTH, InvoiceDate, GETDATE()) <= 12) sub
ORDER BY YearMonth
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = '
SELECT StockCode, ' + #cols2 + '
FROM (
SELECT StockCode,
QtyInvoiced,
CAST([TrnYear] AS NVARCHAR(4))+RIGHT(''00''+CAST([TrnMonth] AS NVARCHAR(2)),2) AS YearMonth
FROM ArTrnDetail
WHERE StockCode NOT LIKE ''%DEM%'' AND StockCode NOT LIKE ''%REF%'' AND StockCode NOT LIKE ''Z%''
) AS X
PIVOT (
SUM(QtyInvoiced)
FOR YearMonth in (' + #cols + ')
) AS PT'
EXECUTE (#query)
The results for each query are correct. Now how do I combine them into one query. So that they return
STOCKCODE | Past 12 Month Sales Per Month | Stock On Hand | Future Purchases
Helicopters | 1 4 5 2 3 4 6 1 3 2 3 2| 15 | 2 3 5 4 6 7 8 4 3 2 8 5
Jam | 2 5 6 4 8 5 8 5 7 2 1 2| 30 | 4 5 6 5 8 7 0 1 2 1 1 4
Frogs | 2 3 2 4 8 5 4 6 8 2 1 3| 7 | 5 7 8 8 6 7 4 0 1 2 1 2
STOCK CODE for the above is the same information from the different tables eg. Helicopters in Inventory is the same as Helicopters in Purchase Orders.
I would suggest the following:
Rewrite #query2 to result in two columns: StockCode and Sales. Instead of selecting each month as a seperate column, concatenate each month in a VARCHAR. You already wrote a variable for #cols for selecting the columns seperately. Keep that for pivoting. Write a variable (#SelSales) to concatenate the results for each month in a VARCHAR and use that in your selection for the Sales column.
Rewrite #query3 to result in two columns: StockCode and Purchases (similar to 1.)
Put your #query1 in a NVARCHAR(MAX) variable (the one selecting the stock).
Write a #query to combine them all.
TSQL outline for #query:
DECLARE #query NVARCHAR(MAX);
SET #query=N'
SELECT
COALESCE(stock.StockCode,sales.StockCode,purchases.StockCode) AS StockCode,
COALESCE(sales.Sales,''0 0 0 0 0 0 0 0 0 0 0 0'') AS Sales,
COALESCE(stock.SOH,0) AS Stock,
COALESCE(purchases.Purchases,''0 0 0 0 0 0 0 0 0 0 0 0'') AS Purchases
FROM
('+#query1+') AS stock
FULL JOIN ('+#query2+') AS sales ON sales.StockCode=stock.StockCode
FULL JOIN ('+#query3+') AS purchases ON purchases.StockCode=stock.StockCode';
EXEC(#query);

SQL CROSS TAB & PIVOT

I am using the following query to retrieve some results
SELECT CONVERT(varchar, TS.StaffID) + CHAR(13)
+ SUBSTRING ( TS.GivenName, 1 , 1 ) + '.' + CHAR(13)
+ TS.Surname AS EmployeeInfo, SH.Hours,ts.UnitID,sh.RowID
FROM dbo.tbl_TimesheetStaff AS TS
Left OUTER JOIN
dbo.tbl_StaffHours AS SH ON
SH.ActivityUnitID = TS.ActivityUnitID
AND Sh.StaffID=ts.StaffID
WHERE TS.UnitID=1
The resulting set looks like
EmployeeInfo Hours UnitID RowID
114 H. Bar 73.71 111 401
114 H. Bar 42.44 111 402
115 M. Cha 20.39 111 401
115 M. Cha 3.616 111 402
116 Q. Xyz 20.39 111 401
116 Q. Xyz 3.61 111 402
Now what I want is to convert the EmployeeInfo column values to column names
114 H. Bar 115 M. Cha 116 Q. Xyz RowID
73.71 20.39 20.39 401
42.44 3.616 3.61 402
The number of rows in EmployeeInfo can vary and hence I need a dynamic pivot function.
Any clues..?
try this:
create table #t table(EmployeeInfo varchar(20), Hours float, UnitID int, RowID int)
insert into #t
SELECT CONVERT(varchar, TS.StaffID) + CHAR(13)
+ SUBSTRING ( TS.GivenName, 1 , 1 ) + '.' + CHAR(13)
+ TS.Surname AS EmployeeInfo, SH.Hours,ts.UnitID,sh.RowID
FROM dbo.tbl_TimesheetStaff AS TS
Left OUTER JOIN
dbo.tbl_StaffHours AS SH ON
SH.ActivityUnitID = TS.ActivityUnitID
AND Sh.StaffID=ts.StaffID
WHERE TS.UnitID=1
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(EmployeeInfo)
from #t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT RowID, ' + #cols + '
from #t
pivot
(
MAX([Hours])
for Code in (' + #cols + ')
) p '
print(#query)
execute(#query)