Reputation: 10638
In SQL Server I have a table like below:
processName initDateTime
processA 2020-06-15 13:31:15.330
processB 2020-06-20 10:00:30.000
processA 2020-06-20 13:31:15.330
...
and so on
I need to group by processName and for each processName I need to get the number of records by month (#byMonth), day (#byDay) and hour (#byHour).
What is the best way to do it? Something as below? What would be the SQL query?
Possible results:
processName Month Day Hour #byMonth #byDay #byHour #total(by process)
processA January 15 17 4 3 2 7
processA January 15 20 4 3 1 7
processA January 20 05 4 2 3 7
processA January 20 13 4 2 1 7
processA March 04 05 3 2 3 7
processA March 04 17 3 2 2 7
processA March 15 05 3 3 3 7
...and so on for the rest of processes name
Upvotes: 0
Views: 132
Reputation: 222382
I think that you want aggregation and window functions:
select
processName,
month(initDateTime),
day(initDateTime),
datepart(hour, initDateTime),
sum(count(*)) over(partition by processName, year(initDateTime), month(initDateTime)) byMonth,
sum(count(*)) over(partition by processName, year(initDateTime), month(initDateTime), day(initDateTime)) byDay,
count(*) byHour
from mytable
group by
processName,
year(initDateTime),
month(initDateTime),
day(initDateTime),
datepart(hour, initDateTime)
Upvotes: 1
Reputation: 69749
Wherever possible, I like to return dates as dates to the caller, so that they can also treat them as dates for things such as sorting, converting to local time, or even making sure that the language shown is relevant. So if it were me, i would do the following:
-- sample data
CREATE TABLE #T (processName VARCHAR(50), initDateTime DATETIME)
INSERT #T (processName, initDateTime)
VALUES
('processA', '2020-06-15 13:31:15.330'),
('processB', '2020-06-20 10:00:30.000'),
('processA', '2020-06-20 13:31:15.330')
SELECT t.processName,
i.InitHour,
ByMonth = SUM(COUNT(*)) OVER(PARTITION BY i.InitMonth),
ByDay = SUM(COUNT(*)) OVER(PARTITION BY i.InitDay),
ByHour = COUNT(*)
FROM #T AS t
CROSS APPLY
( SELECT InitHour = DATEADD(HOUR, DATEDIFF(HOUR, 0, initDateTime), 0),
InitDay = DATEADD(DAY, DATEDIFF(DAY, 0, initDateTime), 0),
InitMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, initDateTime), 0)
) AS i
GROUP BY t.processName, i.InitHour, i.InitDay, i.InitMonth;
Which returns:
processName InitHour ByMonth ByDay ByHour
--------------------------------------------------------------
processA 2020-06-15 13:00:00 3 1 1
processA 2020-06-20 13:00:00 3 2 1
processB 2020-06-20 10:00:00 3 2 1
If you need the day number, month name etc in SQL, you can get these using DATEPART
or DATENAME
, but as above, this is really better handled in the presentation layer, so you can deal with locales, or specific user settings.
Upvotes: 1