我试图为SQL Server编写一些SQL代码。以下是原始数据的示例:
CREATE TABLE TimeTable
(
id int,
startDate Datetime,
endDate Datetime
);
INSERT INTO TimeTable (id, startDate, endDate)
VALUES
(1, '2015/06/01', '2015/06/10'),
(2, '2015/06/03', '2015/06/10'),
(3, '2015/06/05', '2015/06/10'),
(4, '2015/06/03', '2015/06/06'),
(5, '2015/06/01', '2015/06/03');
视觉上数据如下所示:
2015/06/01 | |
2015/06/02 | |
2015/06/03 || ||
2015/06/04 || |
2015/06/05 ||||
2015/06/06 ||||
2015/06/07 |||
2015/06/08 |||
2015/06/09 |||
2015/06/10 |||
这是我想在下面输出的格式(但也可以按小时分组)。
DateByDay CountOnDay
2015/06/01 2
2015/06/02 2
2015/06/03 4
2015/06/04 3
2015/06/05 4
2015/06/06 4
2015/06/07 3
2015/06/08 3
2015/06/09 3
2015/06/10 3
=============================================== ======================== 多谢你们! 我已经重写了它,因为我现在理解生成一个日期时间范围并对数据进行连接。我已经重新设计了这个时间来考虑小时数。
CREATE TABLE TimeTable
(
id int,
startDate Datetime,
endDate Datetime
);
INSERT INTO TimeTable
(id, startDate, endDate)
VALUES
(1, '2015/06/01 01:30', '2015/06/01 07:00'), --FRINGE CASE since 01:30 should still be at June, 01 2015 01:00:00
(2, '2015/06/01 02:00', '2015/06/01 07:00'),
(3, '2015/06/01 03:00', '2015/06/01 07:00'),
(4, '2015/06/01 04:00', '2015/06/01 07:00'),
(5, '2015/06/01 05:00', '2015/06/01 07:00'),
(8, '2015/06/01 06:00', '2015/06/01 07:00');
DECLARE @From DATETIME, @To DATETIME
SET @From = '2015-06-01 00:00:00'
SET @To = '2015-06-02 20:00:00'
SELECT DateHour, count(B.id)
FROM
(
SELECT DATEADD(HOUR,number,@From) DateHour
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(HOUR,number,@From) <= @To
) A
LEFT JOIN TimeTable B
ON DateHour BETWEEN startDate AND endDate
GROUP BY DateHour
http://sqlfiddle.com/#!3/7c36e/2
然而01:30的边缘情况应该出现在凌晨1点。 什么是实现这种条件的最佳方式
DateHour BETWEEN startDate AND endDate
从上午01:00起不起作用不在01:30和07:00之间
答案 0 :(得分:3)
如果你没有datetable
,但知道你想要的月份,你可以使用(我从here得到这个想法):
declare @month int = 6
;With DateTable as (
select distinct dateadd(month,@month-1,dateadd(year,datediff(year,0,getdate()),0))+number DayOfMonth
from master..spt_values A
where number >= 0 and number < day(dateadd(month,@month,0)-1)
)
select DayOfMonth, count(B.id)
from DateTable A
left join TimeTable B
on DayOfMonth between startDate and endDate
group by DayOfMonth
查看Fiddle
答案 1 :(得分:2)
所以,假设你有某种日期表,那很简单:
select
d.thedate,
count (case when d.thedate between t.startdate and t.enddate then 1 else null end)
from
TimeTable t
inner join datetable d
on d.thedate between t.startdate and t.enddate
group by
d.thedate
如果您没有日期表(创建一个!),您可以使用递归CTE来构建最早的开始日期和最新结束日期之间的日期列表:
with dateCTE
as (
select min(startdate) as thedate,
max(enddate) as maxdate
from
timetable
union all
select thedate + 1,
maxdate
from datecte
where thedate + 1 <= datecte.maxdate
)
select
d.thedate,
count (case when d.thedate between t.startdate and t.enddate then 1 else null end)
from
TimeTable t
inner join datecte d
on d.thedate between t.startdate and t.enddate
group by
d.thedate
答案 2 :(得分:0)
以下是直接为表格中的值自定义的版本。表master..spt_values
是一个方便的数字来源。如果您没有日历表,这将非常有用。
with dates as (
select dateadd(day, n.n, d1) as dte
from (select row_number() over (select NULL) - 1 as n
from master..spt_values n
) n join
(select min(startdate) as d1, max(enddate) as d2
from TimeTable
) tt
on dateadd(day, n.n, d1) <= d2
)
select d.dte,
(select count(*)
from TimeTable tt
where d.dte between tt.startdate and tt.enddate
) as cnt
from dates d ;
CTE计算数据表示的所有日期(从最小开始日期到最大结束日期)。外部查询然后计算每个日期的匹配记录数。