我遇到了一个有趣的问题,当然可以使用一些帮助。我有一个查询,可以提取一天中发生的“事件”。目标是按日对事件进行分组,并计算当天发生的事件数量。
我遇到的问题是日期时间字段对于每个事件都有不同的时间,这使得分组变得非常困难。请注意,“TheDate”必须有2个字段 - 一个将显示给用户(NVARCHAR转换),另一个用于进行日期范围搜索。此查询将存储在视图中。
查询虽然没有按照我的意愿执行,也没有考虑到这一点,看起来像这样:
SELECT TheDate, Username, CONVERT(NVARCHAR(10), TheDate, 120) 'Date',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY CONVERT(NVARCHAR(10), TheDate, 120), TheDate, Username
ORDER BY CONVERT(NVARCHAR(10), TheDate, 120)
UNION
SELECT TheDate, Username, 'GrandTotal',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY TheDate, Username
这种分组都搞砸了,原因很明显。我希望按日分组结果,而不是每天10-20行,因为日期时间字段TheDate上列出了小时/分钟/秒。
尝试以某种方式修复此问题,我尝试了类似以下内容:
SELECT * FROM(
SELECT UserName, DATEADD(DAY, DATEDIFF(day, 0, TheDate), 0) AS TheDate,
CONVERT(NVARCHAR(10), TheDate, 120) 'Date',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY CONVERT(NVARCHAR(10), TheDate, 120), TheDate, UserName
ORDER BY CONVERT(NVARCHAR(10), TheDate, 120)
UNION
SELECT Username, DATEADD(DAY, DATEDIFF(day, 0, TheDate), 0) AS TheDate,
'GrandTotal',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY UserName, TheDate) AS X
GROUP BY X.TheDate, X.Date, X.UserName, X.Item1, X.Item2, X.Item3, X.Item4, X.Item5
我的目标是从日期时间中移除时间。可见,在结果中,它起作用了。日期时间结果现在看起来都像
2013-12-24 00:00:00.000
不幸的是,从技术上讲,它没有做任何事情。我每天仍然有10-20行,就像我看到时间一样。
我希望我的结果看起来像这样(记住,这是进入一个视图,所以我不会明显选择Username和TheDate供用户查看。这些仅用于where子句目的):
Date Item2 Item2 Item3 Item4 Item5
2013-05-31 1 30 0 0 129
2013-06-03 0 90 0 15 78
2013-06-04 0 50 0 1 124
2013-06-05 0 100 0 17 58
2013-06-06 0 24 0 0 105
2013-06-07 0 50 0 1 83
2013-06-10 0 45 2 42 64
2013-06-11 3 43 0 14 90
2013-06-12 2 44 0 36 88
2013-06-13 1 34 0 15 92
GRAND TOTAL 7 510 2 141 911
有没有人建议解决此问题的最佳方法,并允许我按天分组每组行,而不是因为日期时间不同而每天多行?
谢谢!
答案 0 :(得分:3)
您正在使用SQL Server 2008,因此请使用cast(xxx as date)
- 一种更简单的语法。并将它们放在select
和group by
子句中:
SELECT * FROM(
SELECT UserName, cast(TheDate as date) AS TheDate,
CONVERT(NVARCHAR(10), TheDate, 120) 'Date',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY CONVERT(NVARCHAR(10), TheDate, 120), cast(TheDate as date), UserName
ORDER BY CONVERT(NVARCHAR(10), TheDate, 120)
UNION
SELECT Username, cast(TheDate as date) AS TheDate,
'GrandTotal',
(SUM(CASE WHEN itemID = 1 THEN 1 ELSE 0 END)) AS Item1,
(SUM(CASE WHEN itemID = 2 THEN 1 ELSE 0 END)) AS Item2,
(SUM(CASE WHEN itemID = 3 THEN 1 ELSE 0 END)) AS Item3,
(SUM(CASE WHEN itemID = 4 THEN 1 ELSE 0 END)) AS Item4,
(SUM(CASE WHEN itemID = 5 THEN 1 ELSE 0 END)) AS Item5
FROM Table1 AS a INNER JOIN
Table2 AS tab2 ON tab2.Table1ID = a.Table1ID LEFT OUTER JOIN
Table3 AS tab3 ON tab3.Table2ID = tab2.Table2ID
WHERE someOtherID = 3 AND UserID = 40
GROUP BY UserName, cast(TheDate as date)) AS X
GROUP BY X.TheDate, X.Date, X.UserName, X.Item1, X.Item2, X.Item3, X.Item4, X.Item5
您的查询存在的问题是您拥有构造:
select <expression> as TheDate
. . .
group by TheDate
其中TheDate
也是表格中的一列。 group by
使用表中的列,而不是计算值。实际上,SQL Server允许在group by
子句中使用列别名。
答案 1 :(得分:2)
如果您想按日期分组,可以将DATETIME
列转换为DATE
类型(在SQL Server 2008或更高版本中)。这将删除时间部分。
SELECT CAST(TheDate AS DATE) as TheDate, ...
GROUP BY CAST(TheDate AS DATE), Username