【问题标题】:Ordering dates for 4 weeks订购日期为 4 周
【发布时间】:2016-09-07 14:17:31
【问题描述】:

我正在编写一个 SQL 查询,用于提取过去 4 周的一些信息。 我的结果有两个问题(见下文)。

第一个问题是,当我回顾 4 周时,范围应该是 8 月 10 日 - 9 月 6 日。当我按“日期”订购时,9 月的日期会移动到结果实际上应该在最后。所以我的结果应该从 10(8 月)开始,到 6(9 月)结束。

第二个问题是我错过了一些随机日期(3、4、13、27)。

Day of the Month    Number of X
1                   125
2                   77
5                   5
6                   23
10                  145
11                  177
12                  116
14                  2
15                  199
16                  154
17                  134
18                  140
19                  154
21                  8
22                  166
23                  145
24                  151
25                  107
26                  79
28                  3
29                  151
30                  163
31                  147

这里是我的查询的一般版本:

DECLARE @startDate datetime, @endDate datetime;
SET @startDate = dateadd(day, -28, GETDATE());
SET @endDate = dateadd(day, -1, GETDATE());

Select DATEPArt(dd, Time) AS 'Day of the Month', count(*) AS ' Number of X' 
from SomeTable ST
where Time >= @startDate
AND Time <  @endDate 
group by DATEPArt(dd, Time)   
order by 'Day of the Month'  

【问题讨论】:

  • 如果您缺少日期数据,您可能需要创建和使用日历表。

标签: sql sql-server tsql datetime sql-order-by


【解决方案1】:

对于第一个问题,您可以按日期排序以获得正确的日期顺序。我使用 convert 来获得一个无时间的日期,以便条目正确分组。

DECLARE @StartDate datetime, @EndDate datetime;
SET @StartDate = DATEADD(day, -28, GETDATE());
SET @EndDate = DATEADD(day, -1, GETDATE());

SELECT 
DATEPART(dd, Convert(date, Time)) AS 'Day of the Month', COUNT(*) AS ' Number of X' 
FROM SomeTable ST
WHERE Time >= @StartDate
AND Time <  @EndDate 
GROUP BY Convert(date, Time) 
ORDER BY Convert(date, Time) 

至于缺少的日子,这更复杂,因为分组依据需要有数据才能工作。

一种选择是创建一个包含所有日期的临时表,然后加入数据。这仍然会留下一个连接未找到任何数据的行,并且可以获得“零”计数。

DECLARE @StartDate datetime, @EndDate datetime;
SET @StartDate = DATEADD(day, -28, GETDATE());
SET @EndDate = DATEADD(day, -1, GETDATE());

--Create temporary table with all days between the two dates
;WITH d(d) AS 
(
  SELECT DATEADD(DAY, n, DATEADD(DAY, DATEDIFF(DAY, 0, @StartDate), 0))
  FROM ( SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate) + 1) 
    n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
    FROM sys.all_objects ORDER BY [object_id] ) AS n
)
--Join in our query to the table temporary table
SELECT  
    DATEPART(dd, d.d) AS 'Day of the Month', 
    COUNT(Time) AS ' Number of X' 
FROM d LEFT OUTER JOIN SomeTable ST ON DATEPART(dd, d.d) = DATEPART(dd, Time) 
                              AND Time >= @StartDate 
                              AND Time <  @EndDate 
GROUP BY d.d
ORDER BY d.d

【讨论】:

  • 以这种方式排序在 ms-sql 中可以正常工作,但在其他形式的 sql 中可能无法正常工作。我已编辑 order by 以改用列索引。
  • 感谢 James,但不幸的是,所做的只是添加一个显示月份的列。 9 月的日期仍然排在首位。
  • 我无法重现,如果运行查询,结果将按月排序,然后按天排序。尽管我注意到我没有将查询更改回您的查询方式。你能复制第二个查询并重试吗?
  • James,不确定我需要输入什么来代替 [object_id]。你能澄清一下吗?
  • 为什么不直接按日期字段排序,日期分开真的有必要吗?因为 12 月到 1 月现在可能会导致年份出现问题,如果您要分开这一年,为什么不按开始日期排序并避免所有日期分开...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 2019-11-14
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多