Related
I have the following table(raw data). I would like to see the data in following format(Formatted Data).
I tried the following query. It produces a rather weird result. Could someone guide me here how to achieve this.
declare #monthnames varchar(100)
select distinct [Month], MonthNumber
into #Months
from Table
order by MonthNumber
SELECT #monthnames = Stuff((SELECT ', ' + [Month]
FROM #Months
order by MonthNumber
FOR XML PATH('')
), 1, 2, '')
declare #query varchar(500)
set #query = 'select CUR,' + #monthnames +
' from ' +
' Pivot ( min(DATE) for [Month] in (' + #monthnames + ') ) as Pivottable ORDER BY CUR'
EXEC (#query)
You don't really need to use Dynamic SQL as you have a fixed number of pivoting columns.
What you are missing is the rn, so that each date appear under different row
SELECT CUR,
[1] as Jan,
[2] as Feb,
[3] as Mar,
[4] as Apr,
[5] as May
FROM (
SELECT CUR, MonthNumber, DATE,
rn = ROW_NUMBER() OVER (PARTITION BY CUR, MonthNumber ORDER BY DATE)
FROM #Table
) AS d
PIVOT
(
MIN(DATE)
FOR MonthNumber IN ([1], [2], [3], [4], [5])
) AS p
declare #t table
(
CUR varchar(10),
[Month] varchar(20),
MonthNumber tinyint,
[Date] date
);
insert into #t(Cur, [Month], MonthNumber, [Date])
values
('AED', 'January', 1, '20200110'),
('AED', 'February', 2, '20200212'),('AED', 'February', 2, '20200215'),
('AED', 'March', 3, '20200305'),('AED', 'March', 3, '20200305'),('AED', 'March', 3, '20200305'),
('AED', 'April', 4, '20200402'),('AED', 'April', 4, '20200412'),('AED', 'April', 4, '20200415'),
('AED', 'June', 6, '20200619'),
('AED', 'August', 8, '20200801'),('AED', 'August', 8, '20200805'),('AED', 'August', 8, '20200810'), ('AED', 'August', 8, '20200824'),
----
('ARS', 'January', 1, '20200118'),
('ARS', 'April', 4, '20200416'),
('ARS', 'May', 5, '20200512'), ('ARS', 'May', 5, '20200513'), ('ARS', 'May', 5, '20200514'),
('ARS', 'September', 9, '20200902'),('ARS', 'September', 9, '20200922');
select CUR, [January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November],[December]
from
(
select CUR, [Date], dense_rank() over(partition by CUR, [Month] /*or MonthNumber*/ order by [Date]) as ranking,
[Month]
from #t
) as t
pivot
(
min([Date]) for [Month] in ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November],[December])
) as pvt
order by CUR;
Please help and thank you very much!
How do I get this result?
http://i.stack.imgur.com/EedXW.png
This is my current result:
http://i.stack.imgur.com/Ydzn0.png
Code:
WITH shiftHours AS
(
SELECT
RowID,
y.EMPLOYEENAME AS EMPLOYEENAME,
-- flatten the first hour to remove the minutes and get the initial current hour
DATEADD(hour, DATEDIFF(hour, 0, ShiftA_Start), 0) AS currentHour,
ShiftA_Start,
ShiftA_End,
DATEPART(hour, ShiftA_Start) AS hourOrdinal,
-- determine how much of the first hour is applicable. if it is minute 0 then the whole hour counts
CAST(CASE
WHEN DATEADD(hour, DATEDIFF(hour, 0, ShiftA_Start), 0) = DATEADD(hour, DATEDIFF(hour, 0, ShiftA_End), 0) THEN DATEDIFF(minute, ShiftA_Start, ShiftA_End) / 60.0
WHEN DATEPART(minute, ShiftA_Start) = 0 THEN 1.0
ELSE (60 - DATEPART(minute, ShiftA_Start)) / 60.0
END AS DECIMAL(5,3)) AS hourValue
FROM
(-- use a ROW_NUMBER() to generate row IDs for the shifts to ensure each row is unique once it gets to the pivot
SELECT
ROW_NUMBER() OVER(ORDER BY ShiftA_Start, ShiftA_End) AS RowID,
EMPLOYEENAME,
ShiftA_Start,
ShiftA_End
FROM
(-- this is where the data gets pulled from the source table and where the data types are converted from string to DATETIME
SELECT
EMPLOYEENAME,
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_Start,
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_end,
CAST(CASE
WHEN DATEPART (day, [ShiftA_Start]) = DATEPART (day, [SHIFTA_END])
THEN CONVERT(DATETIME, LEFT(SHIFTA_end, 17), 103)
WHEN DATEPART (hour, [ShiftA_Start]) = DATEPART (hour, [SHIFTA_END])
THEN CONVERT(DATETIME, LEFT(SHIFTA_end, 17), 103) + '23:59:00.000' END AS VARCHAR(30)) AS S_END
FROM
[DatabaseName].[dbo].[TMS_PEOPLE]
WHERE
CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) IS NOT NULL
AND CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103) IS NOT NULL
AND CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) != CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103)
AND CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) != '1900-01-01 00:00:00.000'
AND CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103) != '1900-01-01 00:00:00.000'
--AND CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) = '2016-01-24 14:09:00.000'
AND EMPLOYEENAME = 'MUHAMMAD BIN PARMIN'
-- this is also where you would add any filtering from the source table such as date ranges
) x
) AS y
UNION ALL
SELECT RowID,
EMPLOYEENAME,
-- add an hour to the currentHour each time the recursive CTE is called
DATEADD(hour, 1, currentHour) AS currentHour,
ShiftA_Start,
ShiftA_End,
DATEPART(hour, DATEADD(hour, 1, currentHour)) AS hourOrdinal,
CAST(CASE
-- when this is the last time period determine the amount of the hour that is applicable
WHEN DATEADD(hour, 2, currentHour) > ShiftA_End THEN DATEPART(minute, ShiftA_End) / 60.0
ELSE 1
END AS DECIMAL(5,3)) AS hourValue
from shiftHours
-- contine recursion until the next hour is after the ShiftEnd
WHERE DATEADD(hour, 1, currentHour) < ShiftA_End
)
SELECT *
FROM (
SELECT RowID,
EMPLOYEENAME,
ShiftA_Start,
ShiftA_End,
hourValue,
hourOrdinal
from shiftHours
) AS t
PIVOT (
SUM(hourValue)
FOR hourOrdinal IN ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23])
) AS pvt
OPTION (MAXRECURSION 0);
JKQDJKBDJAJSDudkbsjkdbjkBhsjkdbnbjasadbjbdjajdbka dhajdkbobKJBDJBAJBDO
In your inner query you have this line
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_end,
should you not use the end of the shift instead?
Consider this 24-hour summary. The problem is that I'm getting 0s returned for hours where values haven't been inserted yet. I believe this is due to the SUM() function call.
SELECT
section,
[21], [22], [23], [0], [1], [2], [3], [4], [5], [6], [7], [8],
[21] + [22] + [23] + [0] + [1] + [2] + [3] + [4] + [5] + [6] + [7] + [8] as s1_total
-- shift 2 fields are ommitted for brievity
FROM (
SELECT
section,
-- hours from 21:00 (1st shift) to 20:00 (2nd shift)
SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END) AS [21],
SUM(CASE WHEN prTime = '22:00:00' THEN Amount ELSE 0 END) AS [22],
SUM(CASE WHEN prTime = '23:00:00' THEN Amount ELSE 0 END) AS [23],
SUM(CASE WHEN prTime = '00:00:00' THEN Amount ELSE 0 END) AS [0],
SUM(CASE WHEN prTime = '01:00:00' THEN Amount ELSE 0 END) AS [1],
SUM(CASE WHEN prTime = '02:00:00' THEN Amount ELSE 0 END) AS [2],
-- ... similar cases are omitted for brieviety
SUM(CASE WHEN prTime = '20:00:00' THEN Amount ELSE 0 END) AS [20]
FROM (
SELECT prTime, prDate, section01 AS Amount, 'section 1' as [Section] FROM SectionsHourlyValues
UNION
SELECT prTime, prDate, section02 AS Amount, 'section 2' as [Section] FROM SectionsHourlyValues
UNION
SELECT prTime, prDate, section03 AS Amount, 'section 3' as [Section] FROM SectionsHourlyValues
) AS U
WHERE
(prDate = CONVERT(DATE, DATEADD(HOUR, -4, CONVERT(DATETIME2(7), #dt, 104))) and prTime > '20:00:00') or
(prDate = CONVERT(DATE, #dt, 104) and prTime <= '20:00:00')
GROUP BY section
) t;
For example, running the query
DECLARE #dt varchar(10) = 'certain_date';
SELECT * from [dbo].[SectionsHourlyValues] WHERE
(prDate = CONVERT(DATE, DATEADD(HOUR, -4, CONVERT(DATETIME2(7), #dt, 104))) and prTime > '20:00:00') or
(prDate = CONVERT(DATE, #dt, 104) and prTime <= '20:00:00');
wouldn't return us the data for say 09:00:00 / section1 whereas the summary would show us 0.
Then I want to show NULL (for not yet inserted records) instead of 0. How do I do that?
How about replacing the 0 with NULL in your conditional aggregation ?
SUM(CASE WHEN etc... ELSE NULL END)
Use NULLIF
ex
NULLIF(SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END),0)
or simply do not use ELSE
SUM(CASE WHEN prTime = '21:00:00' THEN Amount END)
You're getting 0 values not due to the SUM function for values not yet inserted (that would be NULL and would ignored by the SUM function), but because the ELSE of your CASE statement returns 0:
SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END) AS [21]
To solve your problem, you can use NULLIF that is rather similar to CASE:
NULLIF(MyExpressionThatCouldReturn0, 0)
That in your case would be:
NULLIF(SUM(CASE WHEN prTime = '01:00:00' THEN Amount ELSE 0 END),0)
Otherwise, as said before, do not use ELSE in the CASE statement, used as parameter of your SUM:
SUM(CASE WHEN prTime = '21:00:00' THEN Amount END)
Hoping someone can help me. I was able to put together this SQL script but it coming back with minor errors here and there. I'be been trying to debug for over a week now. Please help. the first error message is "Incorrect syntax near ')'." If you fixe that it keeps on throwing more out so I'm thinking I'm not coding this correctly. I am unable to save changes that do work. it tell me the save request was aborted. Working with SQL Server 2008 r2
SELECT
PublicationID AS PubID, (PubNum + '- ' + PubTitle) AS [Pub Descr],
CONVERT(Varchar(10), [Datestamp], 101) AS [Date Printed],
QtyPrinted AS [Qty Printed],
[2] AS [Tyler Inventory],
[1] AS [Central Inventory],
[3] AS [Mailing House Inventory],
(
SELECT SUM(S)
FROM
(
SELECT [1] UNION ALL
SELECT [2] UNION ALL
SELECT [3]
) AS T (S)) AS [Current Inventory],
RecycledQty AS [Recycled],
MailingVendorName AS [Mailing Vendor],
PrintVendorName AS [Print Vendor]
FROM
(
SELECT
PublicationID, LocationID, Balance, PubNum,
PubTitle, ItemPerCase, Datestamp, Deleted,
RecycledQty, MailingVendorName, PrintVendorName,
QtyPrinted
FROM
(
dbo.view_PubInventory_Main_Summary_RAW) x PIVOT (sum(balance) FOR
LocationID IN ([1], [2], [3])) p)
SELECT *
FROM
(SELECT PUBID, [Pub Descr], [Date Printed], [Qty Printed],
[Tyler Inventory], [Central Inventory],
[Mailing House Inventory], [Current Inventory], [Recycled],
[Mailing Vendor]
FROM GG
) AS T
Hard to follow exactly what you're after, but I think you want Current Inventory to just be [1]+[2]+[3], and you didn't alias your subquery. The query at the bottom looks fine.
SELECT PublicationID AS PubID
, PubNum + '- ' + PubTitle AS [Pub Descr]
, CONVERT(VARCHAR(10), [Datestamp], 101) AS [Date Printed]
, QtyPrinted AS [Qty Printed]
, [2] AS [Tyler Inventory]
, [1] AS [Central Inventory]
, [3] AS [Mailing House Inventory]
, [1]+[2]+[3] AS [Current Inventory]
, RecycledQty AS [Recycled]
, MailingVendorName AS [Mailing Vendor]
, PrintVendorName AS [Print Vendor]
FROM ( SELECT PublicationID
, LocationID
, Balance
, PubNum
, PubTitle
, ItemPerCase
, Datestamp
, Deleted
, RecycledQty
, MailingVendorName
, PrintVendorName
, QtyPrinted
FROM dbo.view_PubInventory_Main_Summary_RAW
PIVOT ( SUM(balance) FOR LocationID IN ( [1], [2], [3] ) ) p
)AS Sub
WHY, why, why? Do I get an error:
"Msg 325, Level 15, State 1, Line 17
Incorrect syntax near 'PIVOT'. You may need to set the compatibility level of the current database to a higher value to enable this feature. See help for the stored procedure sp_dbcmptlevel."
For this query?
WITH Offnet7 AS (
SELECT disposition.dispositiondesc, interaction.dispositionid, DATEPART(wk,interaction.ibegintime) as iWeek
FROM interaction INNER JOIN
disposition ON interaction.reasonid = disposition.dispositionid
WHERE interaction.dispositionid = 10 and (reasonid = 20365 or reasonid = 20366 or reasonid = 11168) and
interaction.ibegintime >= '2013-1-1' and
interaction.ibegintime < '2014-1-1'
)
SELECT iWeek, dispositiondesc, count(iWeek) as 'OffnetCounts'
FROM Offnet7
Group by dispositiondesc, iWeek
PIVOT
(
OffnetCounts
for iWeek in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15])
) AS counts
EDIT:
Tried to make a SQL Fiddle, and it choked when I went to "Build Schema." (SQL Noob)
I pulled the types from SQL management studio's object explorer and copied some example data. But this is what I attempted:
CREATE TABLE interaction
([reasonid] int, [dispositionid] int, [ibegintime] datetime)
;
INSERT INTO interaction
([reasonid], [dispositionid], [ibegintime])
VALUES
(20366, 10, '2012-01-31 23:59:48.000'),
(20366, 10, '2012-02-07 14:03:01.000'),
(20366, 10, '2012-02-07 14:06:48.000'),
(20366, 10, '2012-02-13 21:44:10.000'),
(20366, 10, '2012-02-27 21:36:33.000')
;
CREATE TABLE disposition
([dispositionid] int, [predefined] int, [dispositiondesc] varchar(64), [displayvalue] varchar(254))
;
INSERT INTO disposition
([dispositionid], [predefined], [dispositiondesc], [displayvalue])
VALUES
(10, 1, 'TRANSFERRED OFFNET', 'TRANSFERRED OFFNET'),
(11168, 0, 'TAKEDA PASSWORD', 'TAKEDA PASSWORD'),
(15433, 0, 'Voice Mail - TAKEDAEMEA', 'Voice Mail - TAKEDAEMEA'),
(20365, 0, 'TAKEDA iPAD, iPhone or BlackBerry', 'TAKEDA iPAD, iPhone or BlackBerry'),
(20366, 0, 'TAKEDA Concur', 'TAKEDA Concur')
;
Conclusion:
Thanks for all the help Bluefeet!
For anyone interested in this, his first answer WOULD HAVE worked if the SQL compatibility level was set correctly by my DBA. After trying his first answer I got a:
"Msg 102, Level 15, State 1, Line 19 Incorrect syntax near '('."
Because the DBA doesn't have the SQL Server configured with a compatibility level that supports the PIVOT statement.
Your syntax is off. The PIVOT is doing the GROUP BY and an aggregation. It seems to me that you want to be using:
WITH Offnet7 AS
(
SELECT disposition.dispositiondesc,
interaction.dispositionid,
DATEPART(wk,interaction.ibegintime) as iWeek
FROM interaction
INNER JOIN disposition
ON interaction.reasonid = disposition.dispositionid
WHERE interaction.dispositionid = 10
and (reasonid = 20365 or reasonid = 20366 or reasonid = 11168)
and interaction.ibegintime >= '2013-1-1'
and interaction.ibegintime < '2014-1-1'
)
SELECT dispositiondesc,
[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15]
FROM Offnet7
PIVOT
(
count(dispositionid)
for iWeek in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15])
) AS counts;
See Demo
This will create a table of data with the counts of the dispositionid's for each week, grouped by the dispositiondesc.
Edit, this can also be done using an aggregate function with a CASE expression:
SELECT disposition.dispositiondesc,
sum(case when DATEPART(wk,interaction.ibegintime) = 1 then 1 else 0 end) [1],
sum(case when DATEPART(wk,interaction.ibegintime) = 2 then 1 else 0 end) [2],
sum(case when DATEPART(wk,interaction.ibegintime) = 3 then 1 else 0 end) [3],
sum(case when DATEPART(wk,interaction.ibegintime) = 4 then 1 else 0 end) [4],
sum(case when DATEPART(wk,interaction.ibegintime) = 5 then 1 else 0 end) [5],
sum(case when DATEPART(wk,interaction.ibegintime) = 6 then 1 else 0 end) [6],
sum(case when DATEPART(wk,interaction.ibegintime) = 7 then 1 else 0 end) [7],
sum(case when DATEPART(wk,interaction.ibegintime) = 8 then 1 else 0 end) [8],
sum(case when DATEPART(wk,interaction.ibegintime) = 9 then 1 else 0 end) [9],
sum(case when DATEPART(wk,interaction.ibegintime) = 10 then 1 else 0 end) [10],
sum(case when DATEPART(wk,interaction.ibegintime) = 11 then 1 else 0 end) [11],
sum(case when DATEPART(wk,interaction.ibegintime) = 12 then 1 else 0 end) [12],
sum(case when DATEPART(wk,interaction.ibegintime) = 13 then 1 else 0 end) [13],
sum(case when DATEPART(wk,interaction.ibegintime) = 14 then 1 else 0 end) [14],
sum(case when DATEPART(wk,interaction.ibegintime) = 15 then 1 else 0 end) [15]
FROM interaction
INNER JOIN disposition
ON interaction.reasonid = disposition.dispositionid
WHERE interaction.dispositionid = 10
and (reasonid = 20365 or reasonid = 20366 or reasonid = 11168)
and interaction.ibegintime >= '2013-1-1'
and interaction.ibegintime < '2014-1-1'
group by disposition.dispositiondesc;
See SQL Fiddle with Demo