计算2个日期之间每个日期的记录数
Calculate the number of records for each date between 2 dates
我必须针对多轴图表的 return 结果创建查询。我需要计算为 2 个日期之间的每个日期创建的 ID 数。我试过这个:
DECLARE @StartDate datetime2(7) = '11/1/2020',
@EndDate datetime2(7) = '2/22/2021'
;WITH Date_Range_T(d_range) AS
(
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, @EndDate) - @StartDate, 0)
UNION ALL SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < @EndDate
)
SELECT d_range, COUNT(Id) as Total
FROM Date_Range_T
LEFT JOIN [tbl_Support_Requests] on ([tbl_Support_Requests].CreatedDate Between @StartDate AND @EndDate)
GROUP BY d_range ORDER BY d_range ASC
当然,问题出在 ;WITH
上,return 是错误
Operand type clash: datetime2 is incompatible with int.
如果我给它从当前日期起的特定天数,上面的方法就可以工作,比如:
;WITH Date_Range_T(d_range) AS
(
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 6, 0)
UNION ALL SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < GETDATE()
)
哪个 returns:
问题是我不知道如何替换日期范围。
不需要重新发明轮子 - 有很多递归 CTE 日历表的例子,类似于下面。
DECLARE @StartDate date = '01-Nov-2020', @EndDate date = '22-Feb-2021';
WITH Date_Range_T (d_range) AS (
SELECT @StartDate AS d_range
UNION ALL
SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < @EndDate
)
SELECT d_range, COUNT(Id) AS Total
FROM Date_Range_T
LEFT JOIN tbl_Support_Requests R ON R.CreatedDate = d_range
GROUP BY d_range
ORDER BY d_range ASC
-- Set to the max number of days you require
OPTION (MAXRECURSION 366);
评论:
- 为什么要用
datetime2
代替 date
?
- 您确定要
<
结束日期还是 <=
?
- 您是否熟悉
between
的工作原理 - 它并不总是直观的。
- 为所有表格设置别名以提高可读性。
- 分号终止所有语句。
- 一致的大小写使查询更易于阅读。
- 对日期字符串使用明确的日期格式。
改进 ,我建议您使用计数 table 或函数,因为这通常性能更高。
我在下面使用了 Itzik Ben-Gan 的 well-known one:
DECLARE @StartDate date = '2020-11-01', @EndDate date = '2021-02-22';
WITH
L0 AS ( SELECT 1 AS c
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B ),
L2 AS ( SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B ),
Nums AS ( SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L2 )
Date_Range_T (d_range) AS (
SELECT TOP(DATEDIFF(day, @StartDate, @EndDate) + 1)
DATEADD(day, rownum - 1, @StartDate) AS d_range,
DATEADD(day, rownum, @StartDate) AS d_rangeNext
FROM Nums
)
SELECT d_range, COUNT(Id) AS Total
FROM Date_Range_T
LEFT JOIN tbl_Support_Requests R
ON R.CreatedDate >= T.d_range AND R.CreatedDate < T.d_rangeNext
GROUP BY d_range
ORDER BY d_range ASC
我必须针对多轴图表的 return 结果创建查询。我需要计算为 2 个日期之间的每个日期创建的 ID 数。我试过这个:
DECLARE @StartDate datetime2(7) = '11/1/2020',
@EndDate datetime2(7) = '2/22/2021'
;WITH Date_Range_T(d_range) AS
(
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, @EndDate) - @StartDate, 0)
UNION ALL SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < @EndDate
)
SELECT d_range, COUNT(Id) as Total
FROM Date_Range_T
LEFT JOIN [tbl_Support_Requests] on ([tbl_Support_Requests].CreatedDate Between @StartDate AND @EndDate)
GROUP BY d_range ORDER BY d_range ASC
当然,问题出在 ;WITH
上,return 是错误
Operand type clash: datetime2 is incompatible with int.
如果我给它从当前日期起的特定天数,上面的方法就可以工作,比如:
;WITH Date_Range_T(d_range) AS
(
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 6, 0)
UNION ALL SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < GETDATE()
)
哪个 returns:
问题是我不知道如何替换日期范围。
不需要重新发明轮子 - 有很多递归 CTE 日历表的例子,类似于下面。
DECLARE @StartDate date = '01-Nov-2020', @EndDate date = '22-Feb-2021';
WITH Date_Range_T (d_range) AS (
SELECT @StartDate AS d_range
UNION ALL
SELECT DATEADD(DAY, 1, d_range)
FROM Date_Range_T
WHERE DATEADD(DAY, 1, d_range) < @EndDate
)
SELECT d_range, COUNT(Id) AS Total
FROM Date_Range_T
LEFT JOIN tbl_Support_Requests R ON R.CreatedDate = d_range
GROUP BY d_range
ORDER BY d_range ASC
-- Set to the max number of days you require
OPTION (MAXRECURSION 366);
评论:
- 为什么要用
datetime2
代替date
? - 您确定要
<
结束日期还是<=
? - 您是否熟悉
between
的工作原理 - 它并不总是直观的。 - 为所有表格设置别名以提高可读性。
- 分号终止所有语句。
- 一致的大小写使查询更易于阅读。
- 对日期字符串使用明确的日期格式。
改进
我在下面使用了 Itzik Ben-Gan 的 well-known one:
DECLARE @StartDate date = '2020-11-01', @EndDate date = '2021-02-22';
WITH
L0 AS ( SELECT 1 AS c
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B ),
L2 AS ( SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B ),
Nums AS ( SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L2 )
Date_Range_T (d_range) AS (
SELECT TOP(DATEDIFF(day, @StartDate, @EndDate) + 1)
DATEADD(day, rownum - 1, @StartDate) AS d_range,
DATEADD(day, rownum, @StartDate) AS d_rangeNext
FROM Nums
)
SELECT d_range, COUNT(Id) AS Total
FROM Date_Range_T
LEFT JOIN tbl_Support_Requests R
ON R.CreatedDate >= T.d_range AND R.CreatedDate < T.d_rangeNext
GROUP BY d_range
ORDER BY d_range ASC