提示:数据库中最好有一个真实的日期字段,而不仅仅是年/月。这样,除了聚集索引之外,您还可以创建日期索引。
但是,如果你有FullDate
,你会得到同样的错误信息。Year
Month
view contains an expression on result of aggregate function or grouping column
如果您这样做,可能会发生该错误:
SELECT
[Manufacturer]
,[Date] as FullDate
,DATEPART(year,[Date]) as Year
,DATEPART(month,[Date]) as Month
,COUNT_BIG(*) as Count
,SUM(OrderValue) as TotalOrderValue
FROM [dbo].[TABLE1]
Group By
[Manufacturer]
,[Date]
,DATEPART(year,[Date])
,DATEPART(month,[Date])
虽然不是很明显发生了什么,但我认为这是因为它Date
在分组列中查看并Date
在其他列中使用(对于年份和月份)。显然,尽管这在逻辑上应该可行,并且您应该能够像那样进行分组。
我发现了一个让它起作用的技巧:
SELECT
[Manufacturer]
,DATEADD(day, 0, [Date]) as FullDate
,DATEPART(year,[Date])as Year
,DATEPART(month,[Date])as Month
,COUNT_BIG(*) as Count
,SUM(OrderValue) as TotalOrderValue
FROM [dbo].[TABLE1]
Group By
[Manufacturer]
,DATEADD(day, 0, [Date])
,DATEPART(year,[Date])
,DATEPART(month,[Date])
这诱使解析器允许它,现在我可以创建一个单独的索引(在聚集之后)以按 FullDate 搜索。
奖励:我偶然发现这个的真正原因是因为我需要计算昂贵的 ISO_WEEK 和 ISO_YEAR。这是我为此使用的分组子句的最终完整列表:
-- date
DATEADD(day, 0, [Order].OrderDateDt) as OrderDateDt, -- trick! add 0 days to date
-- day / month / year / quarter
DATEPART(day, [Order].OrderDateDt) as OrderDate_day,
DATEPART(month, [Order].OrderDateDt) as OrderDate_month,
DATEPART(year, [Order].OrderDateDt) as OrderDate_year,
DATEPART(quarter, [Order].OrderDateDt) as OrderDate_quarter,
-- iso week
DATEPART(iso_week, [Order].OrderDateDt) as OrderDate_isoweek,
YEAR(DATEADD(day, 26 - DATEPART(iso_week, [Order].OrderDateDt), [Order].OrderDateDt)) as OrderDate_isoyear
确保在 SELECT 和 GROUP BY 中包含所有这些完全相同的内容。