SQL Server PIVOT table for Hours - sql-server

I have a T-SQL query as below which queries a table holding the search data and gets the search hour and count of the rows for that search hour.
SELECT DATEPART(HOUR, aps.CreatedOn) AS SearchHour, COUNT(*) AS ItemCOUNT
FROM ASearches aps
GROUP BY DATEPART(HOUR, aps.CreatedOn)
ORDER BY SearchHour;
As you can see, this does't produce a great result. However, I know that if I use a Pivot table for this and have the hours as column names, that would be better. I tried but I have been failing so far.
Any idea how?

Something like this:
SELECT *
FROM (SELECT DATEPART(HOUR, CreatedOn) AS SearchHour
FROM ASearches) aps
PIVOT (COUNT([SearchHour]) FOR SearchHour 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

Related

multiple pivot on same column in tsql

How can I have pivot define on same column in tsql?
for example:
SELECT * FROM (
SELECT CAST(start_time AS DATE) AS [Date],
DATEPART(hour,start_time) AS [Hour],
Count(is_sale)AS [Sales Count]
,Count(is_not_sale)AS [No Sales Count]
FROM prov_sales WITH(NOLOCK)
GROUP BY CAST(start_time AS DATE), DATEPART(hour,start_time)) AS HourlySalesData
PIVOT( SUM([Sales Count]) FOR [Hour] 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 DatePivot1
PIVOT( SUM([No Sales Count]) FOR [Hour] 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 DatePivot2
My above tsql is not working as I am getting error for the hour column which has repeated values from [1] to [23].
As PIVOT creates Column names from the IN list, you cannot define same column like [1] twice. Although the following solution is not a standard one, but it may server your purpose-
SELECT * FROM (
SELECT CAST(start_time AS DATE) AS [Date],
--Created the hour column twice for Pivoting twice
'Sales_' + CAST(DATEPART(hour,start_time) AS VARCHAR) AS [Hour_Sales],
'NoSales_' + CAST(DATEPART(hour,start_time) AS VARCHAR) AS [Hour_NoSales],
Count(is_sale)AS [Sales Count]
,Count(is_not_sale)AS [No Sales Count]
FROM prov_sales WITH(NOLOCK)
GROUP BY CAST(start_time AS DATE), DATEPART(hour,start_time)) AS HourlySalesData
PIVOT( SUM([Sales Count]) FOR [Hour_Sales] IN ([Sales_0], [Sales_1], [Sales_2], [Sales_3], [Sales_4], [Sales_5], [Sales_6], [Sales_7],
[Sales_8], [Sales_9], [Sales_10],[Sales_11], [Sales_12], [Sales_13], [Sales_14], [Sales_15], [Sales_16],
[Sales_17], [Sales_18], [Sales_19], [Sales_20], [Sales_21], [Sales_22], [Sales_23])) AS DatePivot1
PIVOT( SUM([No Sales Count]) FOR [Hour_NoSales] IN ([NoSales_0], [NoSales_1], [NoSales_2], [NoSales_3], [NoSales_4], [NoSales_5], [NoSales_6], [NoSales_7],
[NoSales_8], [NoSales_9], [NoSales_10],[NoSales_11], [NoSales_12], [NoSales_13], [NoSales_14], [NoSales_15], [NoSales_16],
[NoSales_17], [NoSales_18], [NoSales_19], [NoSales_20], [NoSales_21], [NoSales_22], [NoSales_23])) AS DatePivot2

Count number of occurrences per hour between two dates SQL Server

I've created a temp table #MB that has a record ID (119 rows), start and end date (partial screenshot of the list is below):
I'm trying to get a count of occurrences that happened each hour for each record ID during the start and end date (or number of occurrences each hour when ID was active between two dates).
I've used this code:
SELECT *
FROM
(SELECT
ISNULL(CAST(part AS VARCHAR(5)), 'Total') AS part,
COUNT(*) AS part_count
FROM
(SELECT DATEPART([HOUR], [Start]) AS part
FROM #MB) grp
GROUP BY
GROUPING SETS((part),())
) pre
PIVOT
(MAX(part_count)
FOR part 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], Total)
) pvt;
but it counts only records based on the start date (don't count each hour between two dates) and I stuck on how to generate occurrences per hour for each ID between two dates that I can later use to pre-aggregate and pivot.
first, you need to generate the list of rows for each hour
here i am using a recursive cte query to do it
; with MB as
(
select ID, [Start], [End], [Date] = [Start]
from #MB
union all
select ID, [Start], [End], [Date] = dateadd(hour, 1, convert(date, c.[Date]))
from MB c
where dateadd(hour, 1, c.[Date]) < [End]
)
select *
from MB
so in your pivot query , just change to this
; with MB as
(
select ID, [Start], [End], [Date] = [Start]
from #MB
union all
select ID, [Start], [End], [Date] = DATEADD(HH,DATEPART(HH,[Start]),CAST(CAST([Start] AS DATE) AS DATETIME))
from MB c
where dateadd(hour, 1, c.[Date]) < [End]
)
SELECT *
FROM (
SELECT ISNULL(CAST(part AS VARCHAR(5)), 'Total') AS part,
COUNT(*) AS part_count
FROM (
SELECT DATEPART([HOUR], [Date]) AS part
FROM MB -- changed to the cte
) grp
GROUP BY
GROUPING SETS((part),())
) pre
PIVOT (MAX(part_count) FOR part 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], Total)) pvt;

Running sum and percentage calculated on a specific row in pivot table

I wrote this stored procedure that returns the data perfectly as expected in an Excel-like table. Now I would like to add 2 columns:
Sum of the values of all previous columns
Calculate the percentage of this sum calculated on the sum of the last row
I tried to calculate directly in the first select but no way.
Any suggestion is appreciated.
Thanks.
CREATE PROCEDURE proc_presenze
(
#month VARCHAR(6),
#group INT
)
AS
BEGIN
SELECT FINCode, Nachname, Vorname, Gruppe, [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]
FROM (SELECT BK_Athleten.FINCode, BK_Athleten.Nachname, BK_Athleten.Vorname, BK_Athleten.Gruppe, RIGHT(BK_Einheiten.Datum, 2) AS Day, BK_Anwesend.IDPres
FROM BK_Anwesend INNER JOIN
BK_Athleten ON BK_Anwesend.FINCode = BK_Athleten.FINCode INNER JOIN
BK_Einheiten ON BK_Anwesend.IDEinheit = BK_Einheiten.IDEinheit
WHERE BK_Athleten.Gruppe = #group AND LEFT(BK_Einheiten.Datum, 6) = #month) AS PVT
PIVOT
(
Count(IDPres)
FOR Day IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15],
[16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31] )
) AS PRT
END

How to find average from pivot table in SQL Server?

I am trying to capture transactions per hour between given ranges. And i need to identify the last one week of average transactions.
here i am facing some issue.
Below is my trail:
[Table Structure]
[Current Result]
[Query]
SELECT *
FROM (SELECT
CONVERT(DATE, TimeStamp) AS [Date],
DATEPART(hour,TimeStamp) AS [Hour],
sum(CASE WHEN Result = 'F' THEN 1 ELSE 0 END) AS FAIL
FROM TableName
where TimeStamp between '2018-05-12 00:00:00' and '2018-05-24 23:00:00'
GROUP BY CONVERT(DATE,TimeStamp), DATEPART(hour,TimeStamp)) AS HourlyData
PIVOT( SUM(FAILS) FOR [Hour] IN ( [8], [9], [10],[11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23])
) AS DatePivot
-- avg([Hour] ) over(partition by DATEPART(hour,TimeStamp)) Avg_Item
[Table strcture,Current result and expected result][1]
Anybody please correct me how to find average? Tried with Over clause but not sure which column I need to add in the script.
[1]: https://i.stack.imgur.com/DeQYY.jpg
Below code should give you the expected result.
; WITH CTE AS
(
SELECT *
FROM (SELECT
CONVERT(DATE, TimeStamp) AS [Date],
DATEPART(hour,TimeStamp) AS [Hour],
sum(CASE WHEN Result = 'F' THEN 1.0 ELSE 0.0 END) AS FAIL
FROM #tmp
where TimeStamp between '2017-01-10 00:00:00' and '2018-05-24 23:00:00'
GROUP BY CONVERT(DATE,TimeStamp), DATEPART(hour,TimeStamp)) AS HourlyData
PIVOT( SUM(FAIL) FOR [Hour] IN ( [8], [9], [10],[11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23])
) AS DatePivot
)
SELECT *
FROM (SELECT
CONVERT(VARCHAR(11), TimeStamp) AS [Date],
DATEPART(hour,TimeStamp) AS [Hour],
sum(CASE WHEN Result = 'F' THEN 1.0 ELSE 0.0 END) AS FAIL
FROM #tmp
where TimeStamp between '2017-01-10 00:00:00' and '2018-05-24 23:00:00'
GROUP BY CONVERT(VARCHAR(11),TimeStamp), DATEPART(hour,TimeStamp)) AS HourlyData
PIVOT( SUM(FAIL) FOR [Hour] IN ( [8], [9], [10],[11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23])
) AS DatePivot
UNION ALL
SELECT 'AVERAGE',AVG([8]),AVG([9]),AVG([10]),AVG([11]),AVG([12]),AVG([13]),AVG([14]),AVG([15]),AVG([16]),AVG([17]),AVG([18]),AVG([19]),
AVG([20]),AVG([21]),AVG([22]),AVG([23])
FROM CTE

Stored Procedure Error

I'm getting the following error when I run this code: Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ')'. Any ideas on how to fix this? Any help would be appreciated.
Declare #Month int
Declare #Year int
Declare #newYear int
Declare #EndYearMonth int
Declare #PreviousMonthInt int
Declare #OldYear int
Declare #PreviousMonthName varchar(10)
Declare #NextMonthName varchar(10)
Declare #SQL nvarchar(max)
DECLARE #ParameterDefinition AS NVARCHAR(100)
SET #ParameterDefinition = '#Month int, #Year int, #newYear int, #EndYearMonth int, #PreviousMonthInt int, #OldYear int, #PreviousMonthName varchar(10), #NextMonthName varchar(10)'
Set #SQL = 'Select Y.*, X.* from (Select T1.[1], T1.[2], T1.[3], T1.[4], T1.[5], T1.[6], T1.[7], T1.[8], T1.[9], T1.[10], T1.[11], T1.[12], T1.[13], T1.[14], T1.[15], T1.[16], T1.[17], T1.[18], T1.[19], T1.[20], T1.[21], T1.[22], T1.[23], T1.[24], T1.[25], T1.[26], T1.[27], T1.[28], T1.[29], T1.[30], T1.[31], T2.[1] as February1, T2.DoctorName from (SELECT [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31], DoctorName FROM (SELECT DoctorName, WeekDay, DayType FROM View_GridbyWeekDay where TheMonth = #Month and TheYear = #Year) ps PIVOT ( Max(DayType) FOR WeekDay IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]) ) AS pvt) as T1 Left outer Join (SELECT [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31], DoctorName FROM (SELECT DoctorName, WeekDay, DayType FROM View_GridbyWeekDay where TheMonth = #EndYearMonth and TheYear = #newYear) ps PIVOT ( Max(DayType) FOR WeekDay IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]) ) AS pvt) as T2 on (T1.DoctorName = T2.DoctorName)) as X Left Outer Join (Select DoctorName, [27] as December27, [28] as December28, [29] as December29, [30] as December30, [31] as December31 FROM (SELECT DoctorName, WeekDay, DayType FROM View_GridbyWeekDay where TheMonth = #PreviousMonthInt and TheYear = #OldYear) ps PIVOT ( Max(DayType) FOR WeekDay IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]) ) AS pvt) as Y on (X.DoctorName = Y.DoctorName) Order by X.DoctorName asc '
EXECUTE sp_executesql #SQL, #ParameterDefinition, #Month, #Year, #newYear, #EndYearMonth, #PreviousMonthInt, #OldYear, #PreviousMonthName, #NextMonthName
You're missing at least one ending parentheses for your PIVOT command.
Edit: Looks like you have one too many.
I took all of the text out of your statement and just left the parentheses. This is what it looks like:
Select Y.*, X.* from
((()(()()))(()(()))())(()(()))()
As #George Stocker said, You're missing at least one ending parentheses for your PIVOT command.
try taking your #SQL string in an editor and breaking it up onto multiple lines and indenting it properly, and you'll probably notice where the missing ")" should be.

Resources