How to group and count by date and 8-hr interval on those dates in datetime SQL column?
I have a table with a column visit_date
that is a datetime
object with format YYYY-MM-DD HH:MI:SS
that looks like the following:
visit_date |visit_id
-------------------|-----
2010-11-01 00:02:00|92314
2010-11-01 23:05:21|23498
2010-11-01 12:42:31|12343
2010-11-02 05:13:21|79881
2010-11-02 14:35:15|22134
2010-11-02 16:12:23|12348
2010-11-03 01:22:44|12384
2010-11-03 05:23:41|12394
2010-11-03 15:13:55|99384
I would like to group by date and by 8-hr window on that date such that I have:
interval |count
-------------------|-----
2010-11-01 00:00:00|1
2010-11-01 08:00:00|2
2010-11-01 16:00:00|3
2010-11-02 00:00:00|4
2010-11-02 08:00:00|5
2010-11-02 16:00:00|6
2010-11-03 00:00:00|7
2010-11-03 08:00:00|8
2010-11-03 16:00:00|9
My original query (using only dates) was:
SELECT CAST(visit_date as DATE), count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE)
ORDER BY CAST(visit_date as DATE)
But that only groups by date.
Is there a recommended way to get interval counts for each interval per day? I have seen implementations using DATEADD
and DATEPART
but not sure which makes the most sense in this situation.
Thanks!
sql sql-server
add a comment |
I have a table with a column visit_date
that is a datetime
object with format YYYY-MM-DD HH:MI:SS
that looks like the following:
visit_date |visit_id
-------------------|-----
2010-11-01 00:02:00|92314
2010-11-01 23:05:21|23498
2010-11-01 12:42:31|12343
2010-11-02 05:13:21|79881
2010-11-02 14:35:15|22134
2010-11-02 16:12:23|12348
2010-11-03 01:22:44|12384
2010-11-03 05:23:41|12394
2010-11-03 15:13:55|99384
I would like to group by date and by 8-hr window on that date such that I have:
interval |count
-------------------|-----
2010-11-01 00:00:00|1
2010-11-01 08:00:00|2
2010-11-01 16:00:00|3
2010-11-02 00:00:00|4
2010-11-02 08:00:00|5
2010-11-02 16:00:00|6
2010-11-03 00:00:00|7
2010-11-03 08:00:00|8
2010-11-03 16:00:00|9
My original query (using only dates) was:
SELECT CAST(visit_date as DATE), count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE)
ORDER BY CAST(visit_date as DATE)
But that only groups by date.
Is there a recommended way to get interval counts for each interval per day? I have seen implementations using DATEADD
and DATEPART
but not sure which makes the most sense in this situation.
Thanks!
sql sql-server
1
How can you makecount
column? I don't see any logic in it
– D-Shih
Nov 19 '18 at 23:19
add a comment |
I have a table with a column visit_date
that is a datetime
object with format YYYY-MM-DD HH:MI:SS
that looks like the following:
visit_date |visit_id
-------------------|-----
2010-11-01 00:02:00|92314
2010-11-01 23:05:21|23498
2010-11-01 12:42:31|12343
2010-11-02 05:13:21|79881
2010-11-02 14:35:15|22134
2010-11-02 16:12:23|12348
2010-11-03 01:22:44|12384
2010-11-03 05:23:41|12394
2010-11-03 15:13:55|99384
I would like to group by date and by 8-hr window on that date such that I have:
interval |count
-------------------|-----
2010-11-01 00:00:00|1
2010-11-01 08:00:00|2
2010-11-01 16:00:00|3
2010-11-02 00:00:00|4
2010-11-02 08:00:00|5
2010-11-02 16:00:00|6
2010-11-03 00:00:00|7
2010-11-03 08:00:00|8
2010-11-03 16:00:00|9
My original query (using only dates) was:
SELECT CAST(visit_date as DATE), count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE)
ORDER BY CAST(visit_date as DATE)
But that only groups by date.
Is there a recommended way to get interval counts for each interval per day? I have seen implementations using DATEADD
and DATEPART
but not sure which makes the most sense in this situation.
Thanks!
sql sql-server
I have a table with a column visit_date
that is a datetime
object with format YYYY-MM-DD HH:MI:SS
that looks like the following:
visit_date |visit_id
-------------------|-----
2010-11-01 00:02:00|92314
2010-11-01 23:05:21|23498
2010-11-01 12:42:31|12343
2010-11-02 05:13:21|79881
2010-11-02 14:35:15|22134
2010-11-02 16:12:23|12348
2010-11-03 01:22:44|12384
2010-11-03 05:23:41|12394
2010-11-03 15:13:55|99384
I would like to group by date and by 8-hr window on that date such that I have:
interval |count
-------------------|-----
2010-11-01 00:00:00|1
2010-11-01 08:00:00|2
2010-11-01 16:00:00|3
2010-11-02 00:00:00|4
2010-11-02 08:00:00|5
2010-11-02 16:00:00|6
2010-11-03 00:00:00|7
2010-11-03 08:00:00|8
2010-11-03 16:00:00|9
My original query (using only dates) was:
SELECT CAST(visit_date as DATE), count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE)
ORDER BY CAST(visit_date as DATE)
But that only groups by date.
Is there a recommended way to get interval counts for each interval per day? I have seen implementations using DATEADD
and DATEPART
but not sure which makes the most sense in this situation.
Thanks!
sql sql-server
sql sql-server
asked Nov 19 '18 at 22:19
user50710user50710
106112
106112
1
How can you makecount
column? I don't see any logic in it
– D-Shih
Nov 19 '18 at 23:19
add a comment |
1
How can you makecount
column? I don't see any logic in it
– D-Shih
Nov 19 '18 at 23:19
1
1
How can you make
count
column? I don't see any logic in it– D-Shih
Nov 19 '18 at 23:19
How can you make
count
column? I don't see any logic in it– D-Shih
Nov 19 '18 at 23:19
add a comment |
3 Answers
3
active
oldest
votes
Add the hours in to what you group and count:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
The hour function returns the hour number of the passed date, divide it by 8 to get an int of the interval, so 0 to 7 becomes 0, 8 to 16 becomes 1 etc
If you want it back as a time pegged to a round 8h multiply it by 8 again and format it to NN:00:00, or add it to the date, thus:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
This basically rounds the hours down to the lesser 8h market and adds that to midnight. Two casts are required (probably) on the date because DATEADD won't add hours to a date, only a datetime but we need the cast to date to peg the tine element to midnight
If you want there to be a date and a 0 count for periods where no events took place, use a numbers table or row generator and create a sequence of dates to left join your real data onto, then count the real data grouped by the fake dates
Thanks, this makes a lot of sense. To reformat it, would I simply substituteHOUR(visit_date)/8 as ival8h
withFORMAT(HOUR(visit_date), '##:00:00')
?
– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 andformat(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits
– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternativelydate_add
your(hour(visit_date)/8)*8
hours to yourcast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further
– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
add a comment |
Use a cross apply
to form 4 shift boundary values, then use those in a case expression
to genertate the group by
values
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
result:
+----+---------------------+-------+
| | shift | count |
+----+---------------------+-------+
| 1 | 01.11.2010 00:00:00 | 1 |
| 2 | 01.11.2010 08:00:00 | 1 |
| 3 | 01.11.2010 16:00:00 | 1 |
| 4 | 02.11.2010 00:00:00 | 1 |
| 5 | 02.11.2010 08:00:00 | 1 |
| 6 | 02.11.2010 16:00:00 | 1 |
| 7 | 03.11.2010 00:00:00 | 2 |
| 8 | 03.11.2010 08:00:00 | 1 |
+----+---------------------+-------+
add a comment |
I think the canonical way in SQL Server is to use dateadd()
and datediff()
:
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53383471%2fhow-to-group-and-count-by-date-and-8-hr-interval-on-those-dates-in-datetime-sql%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Add the hours in to what you group and count:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
The hour function returns the hour number of the passed date, divide it by 8 to get an int of the interval, so 0 to 7 becomes 0, 8 to 16 becomes 1 etc
If you want it back as a time pegged to a round 8h multiply it by 8 again and format it to NN:00:00, or add it to the date, thus:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
This basically rounds the hours down to the lesser 8h market and adds that to midnight. Two casts are required (probably) on the date because DATEADD won't add hours to a date, only a datetime but we need the cast to date to peg the tine element to midnight
If you want there to be a date and a 0 count for periods where no events took place, use a numbers table or row generator and create a sequence of dates to left join your real data onto, then count the real data grouped by the fake dates
Thanks, this makes a lot of sense. To reformat it, would I simply substituteHOUR(visit_date)/8 as ival8h
withFORMAT(HOUR(visit_date), '##:00:00')
?
– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 andformat(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits
– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternativelydate_add
your(hour(visit_date)/8)*8
hours to yourcast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further
– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
add a comment |
Add the hours in to what you group and count:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
The hour function returns the hour number of the passed date, divide it by 8 to get an int of the interval, so 0 to 7 becomes 0, 8 to 16 becomes 1 etc
If you want it back as a time pegged to a round 8h multiply it by 8 again and format it to NN:00:00, or add it to the date, thus:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
This basically rounds the hours down to the lesser 8h market and adds that to midnight. Two casts are required (probably) on the date because DATEADD won't add hours to a date, only a datetime but we need the cast to date to peg the tine element to midnight
If you want there to be a date and a 0 count for periods where no events took place, use a numbers table or row generator and create a sequence of dates to left join your real data onto, then count the real data grouped by the fake dates
Thanks, this makes a lot of sense. To reformat it, would I simply substituteHOUR(visit_date)/8 as ival8h
withFORMAT(HOUR(visit_date), '##:00:00')
?
– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 andformat(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits
– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternativelydate_add
your(hour(visit_date)/8)*8
hours to yourcast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further
– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
add a comment |
Add the hours in to what you group and count:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
The hour function returns the hour number of the passed date, divide it by 8 to get an int of the interval, so 0 to 7 becomes 0, 8 to 16 becomes 1 etc
If you want it back as a time pegged to a round 8h multiply it by 8 again and format it to NN:00:00, or add it to the date, thus:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
This basically rounds the hours down to the lesser 8h market and adds that to midnight. Two casts are required (probably) on the date because DATEADD won't add hours to a date, only a datetime but we need the cast to date to peg the tine element to midnight
If you want there to be a date and a 0 count for periods where no events took place, use a numbers table or row generator and create a sequence of dates to left join your real data onto, then count the real data grouped by the fake dates
Add the hours in to what you group and count:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
The hour function returns the hour number of the passed date, divide it by 8 to get an int of the interval, so 0 to 7 becomes 0, 8 to 16 becomes 1 etc
If you want it back as a time pegged to a round 8h multiply it by 8 again and format it to NN:00:00, or add it to the date, thus:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
This basically rounds the hours down to the lesser 8h market and adds that to midnight. Two casts are required (probably) on the date because DATEADD won't add hours to a date, only a datetime but we need the cast to date to peg the tine element to midnight
If you want there to be a date and a 0 count for periods where no events took place, use a numbers table or row generator and create a sequence of dates to left join your real data onto, then count the real data grouped by the fake dates
edited Nov 20 '18 at 8:56
answered Nov 19 '18 at 23:27
Caius JardCaius Jard
11.6k21239
11.6k21239
Thanks, this makes a lot of sense. To reformat it, would I simply substituteHOUR(visit_date)/8 as ival8h
withFORMAT(HOUR(visit_date), '##:00:00')
?
– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 andformat(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits
– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternativelydate_add
your(hour(visit_date)/8)*8
hours to yourcast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further
– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
add a comment |
Thanks, this makes a lot of sense. To reformat it, would I simply substituteHOUR(visit_date)/8 as ival8h
withFORMAT(HOUR(visit_date), '##:00:00')
?
– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 andformat(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits
– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternativelydate_add
your(hour(visit_date)/8)*8
hours to yourcast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further
– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
Thanks, this makes a lot of sense. To reformat it, would I simply substitute
HOUR(visit_date)/8 as ival8h
with FORMAT(HOUR(visit_date), '##:00:00')
?– user50710
Nov 20 '18 at 2:19
Thanks, this makes a lot of sense. To reformat it, would I simply substitute
HOUR(visit_date)/8 as ival8h
with FORMAT(HOUR(visit_date), '##:00:00')
?– user50710
Nov 20 '18 at 2:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 and format(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits– Caius Jard
Nov 20 '18 at 7:19
Hour(visit_date)/8
should give 0 1 or 2, so I think you'll need to multiply it by 8 again to get 0 8 or 16 and format(.., '00":00:00"')
- FORMAT obeys the .net formatting system so any literal text is surrounded by speech marks, the first 00 being used to pad the number out to double digits– Caius Jard
Nov 20 '18 at 7:19
That being said, you could alternatively
date_add
your (hour(visit_date)/8)*8
hours to your cast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further– Caius Jard
Nov 20 '18 at 7:25
That being said, you could alternatively
date_add
your (hour(visit_date)/8)*8
hours to your cast(visit_date as date)
(midnight) if you want to keep it as a datetime or work with it further– Caius Jard
Nov 20 '18 at 7:25
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
Added a second query implementing the above
– Caius Jard
Nov 20 '18 at 8:56
add a comment |
Use a cross apply
to form 4 shift boundary values, then use those in a case expression
to genertate the group by
values
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
result:
+----+---------------------+-------+
| | shift | count |
+----+---------------------+-------+
| 1 | 01.11.2010 00:00:00 | 1 |
| 2 | 01.11.2010 08:00:00 | 1 |
| 3 | 01.11.2010 16:00:00 | 1 |
| 4 | 02.11.2010 00:00:00 | 1 |
| 5 | 02.11.2010 08:00:00 | 1 |
| 6 | 02.11.2010 16:00:00 | 1 |
| 7 | 03.11.2010 00:00:00 | 2 |
| 8 | 03.11.2010 08:00:00 | 1 |
+----+---------------------+-------+
add a comment |
Use a cross apply
to form 4 shift boundary values, then use those in a case expression
to genertate the group by
values
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
result:
+----+---------------------+-------+
| | shift | count |
+----+---------------------+-------+
| 1 | 01.11.2010 00:00:00 | 1 |
| 2 | 01.11.2010 08:00:00 | 1 |
| 3 | 01.11.2010 16:00:00 | 1 |
| 4 | 02.11.2010 00:00:00 | 1 |
| 5 | 02.11.2010 08:00:00 | 1 |
| 6 | 02.11.2010 16:00:00 | 1 |
| 7 | 03.11.2010 00:00:00 | 2 |
| 8 | 03.11.2010 08:00:00 | 1 |
+----+---------------------+-------+
add a comment |
Use a cross apply
to form 4 shift boundary values, then use those in a case expression
to genertate the group by
values
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
result:
+----+---------------------+-------+
| | shift | count |
+----+---------------------+-------+
| 1 | 01.11.2010 00:00:00 | 1 |
| 2 | 01.11.2010 08:00:00 | 1 |
| 3 | 01.11.2010 16:00:00 | 1 |
| 4 | 02.11.2010 00:00:00 | 1 |
| 5 | 02.11.2010 08:00:00 | 1 |
| 6 | 02.11.2010 16:00:00 | 1 |
| 7 | 03.11.2010 00:00:00 | 2 |
| 8 | 03.11.2010 08:00:00 | 1 |
+----+---------------------+-------+
Use a cross apply
to form 4 shift boundary values, then use those in a case expression
to genertate the group by
values
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
result:
+----+---------------------+-------+
| | shift | count |
+----+---------------------+-------+
| 1 | 01.11.2010 00:00:00 | 1 |
| 2 | 01.11.2010 08:00:00 | 1 |
| 3 | 01.11.2010 16:00:00 | 1 |
| 4 | 02.11.2010 00:00:00 | 1 |
| 5 | 02.11.2010 08:00:00 | 1 |
| 6 | 02.11.2010 16:00:00 | 1 |
| 7 | 03.11.2010 00:00:00 | 2 |
| 8 | 03.11.2010 08:00:00 | 1 |
+----+---------------------+-------+
answered Nov 19 '18 at 23:20
Used_By_AlreadyUsed_By_Already
23k21938
23k21938
add a comment |
add a comment |
I think the canonical way in SQL Server is to use dateadd()
and datediff()
:
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;
add a comment |
I think the canonical way in SQL Server is to use dateadd()
and datediff()
:
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;
add a comment |
I think the canonical way in SQL Server is to use dateadd()
and datediff()
:
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;
I think the canonical way in SQL Server is to use dateadd()
and datediff()
:
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;
answered Nov 20 '18 at 3:04
Gordon LinoffGordon Linoff
769k35303404
769k35303404
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53383471%2fhow-to-group-and-count-by-date-and-8-hr-interval-on-those-dates-in-datetime-sql%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
How can you make
count
column? I don't see any logic in it– D-Shih
Nov 19 '18 at 23:19