【发布时间】:2011-03-12 23:22:17
【问题描述】:
现在,我在 SQL Server 中使用 DATETIME 列存储许多记录,该列使用 GETUTCDATE() 存储当前时间戳。这样可以确保我们始终存储准确的日期,而不必担心诸如“这是我的时间是 2:00 还是你的时间是 2:00?”之类的问题。使用 UTC 可确保我们准确地知道它发生的时间,无论时区如何。
但是,我有一个查询,基本上按日期对这些记录进行分组。此查询的简化版本如下所示:
SELECT [created], SUM([amount]) AS [amount]
FROM (
SELECT [amount], LEFT(CONVERT(VARCHAR, [created], 120), 10) AS [created]
FROM (
SELECT [amount], DATEADD(HOUR, -5, [created]) AS [created]
FROM [sales]
WHERE [organization] = 1
) AS s
) AS s
GROUP BY [created]
ORDER BY [created] ASC
显然,这个查询远非理想——我在这里的全部原因是询问如何改进它。首先,它确实(在大多数情况下)实现了我在这里寻找的目标——它有按日期分组的东西,其他值也相应地聚合在一起。但它没有完成的是正确处理夏令时。
我住在威斯康星州麦迪逊市,我们是中部时间,所以在 3 月到 11 月之间我们是 UTC-5,否则我们是 UTC-6。这就是为什么您会在代码中看到 -5 作为快速破解以使其正常工作的原因。
问题是,如果我运行这个查询,并且有记录落在夏令时转换的两边,它可能会错误地对事物进行分组。例如,如果表格看起来像这样:
+----+--------+---------------------+
| id | amount | created |
+----+--------+---------------------+
| 1 | 100.00 | 2010-04-02 06:00:00 |
| 2 | 50.00 | 2010-04-02 04:30:00 |
| 3 | 75.00 | 2010-04-02 03:00:00 |
| 4 | 150.00 | 2010-03-02 07:00:00 |
| 5 | 25.00 | 2010-03-02 05:30:00 |
| 6 | 50.00 | 2010-03-02 04:00:00 |
+----+--------+---------------------+
我的查询将返回:
+------------+--------+
| created | amount |
+------------+--------+
| 2010-03-01 | 50.00 |
| 2010-03-02 | 175.00 |
| 2010-04-01 | 125.00 |
| 2010-04-02 | 100.00 |
+------------+--------+
但是,理想情况下它应该返回这个:
+------------+--------+
| created | amount |
+------------+--------+
| 2010-03-01 | 75.00 |
| 2010-03-02 | 150.00 |
| 2010-04-01 | 125.00 |
| 2010-04-02 | 100.00 |
+------------+--------+
问题是,如果我只是减去一个固定的-5,那么四月是正确的,但三月不是,但如果我改为减去一个固定的-6,那么三月是正确的,但四月不是。我真正需要做的是以了解夏令时并可以相应调整的方式转换到适当的时区。我可以用 SQL 查询来做到这一点吗?如何编写此查询?
【问题讨论】:
标签: sql sql-server tsql utc dst