我有两个表: Orders 和 ODetail 。我想创建一个表格,显示按年份,季度和产品线分组的2012年销售总额(这是一个案例)。这是我的SQL代码:
SELECT * FROM
(SELECT
YEAR(o.OrderDate) 'Year', DATEPART(Quarter, o.OrderDate) 'Quarter',
CASE
WHEN SUBSTRING (od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END ProductLine,
SUM(od.QPrice*od.Quantity)
FROM Orders o, ODetail od
WHERE o.OrderNum=od.OrderNum
AND YEAR(o.OrderDate)=2012
)a
GROUP BY a.Year, a.Quarter, a.ProductLine
出于某种原因,我仍然收到与GROUP BY相关的错误。当我尝试对除SUM列之外的所有列进行分组时,查询工作正常。有任何想法吗?
答案 0 :(得分:2)
GROUP BY
将告知哪些列已分组并应用于聚合函数,在本例中为SUM
。如果您将内部查询(您将别名a
)视为单个查询,则会更容易看到错误。然后,您会看到自己有SUM
但没有GROUP BY
。
当您GROUP BY
列Year, Quarter, ProductLine
时,您要“选择与年份,季度和产品系列匹配的多个行,但随后将其汇总并汇总Price*Quantity
的值”
因此,您可以将GROUP BY
与内部查询放在一起:
SELECT * FROM
(SELECT
YEAR(o.OrderDate) 'Year', DATEPART(Quarter, o.OrderDate) 'Quarter',
CASE
WHEN SUBSTRING (od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END ProductLine,
SUM(od.QPrice*od.Quantity)
FROM Orders o, ODetail od
WHERE o.OrderNum=od.OrderNum
AND YEAR(o.OrderDate)=2012
GROUP BY Year, Quarter, ProductLine
)a
其中A)使内部查询变得多余,B)可能会抱怨没有名为Year
或ProductLine
的列。这可能是您使用内部查询的原因。您必须重复内联字段定义:
GROUP BY YEAR(o.OrderDate), DATEPART(Quarter, o.OrderDate), CASE
WHEN SUBSTRING (od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END
或者你可以按列位置别名(颤抖)分组:
GROUP BY 1, 2, 3
警告:如果您的查询发生更改,列别名将会更改,并且可能无法维护,但适用于即席查询。
最后,您可以将GROUP BY
移到外面,而不是移动SUM
:
SELECT a.Year, a.Quarter, a.ProductLine, SUM(a.QPrice*a.Quantity) FROM
(SELECT
YEAR(o.OrderDate) 'Year', DATEPART(Quarter, o.OrderDate) 'Quarter',
CASE
WHEN SUBSTRING (od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END ProductLine,
od.QPrice,
od.Quantity
FROM Orders o, ODetail od
WHERE o.OrderNum=od.OrderNum
AND YEAR(o.OrderDate)=2012
) a
GROUP BY a.Year, a.Quarter, a.ProductLine
请注意,您必须避免选择*
,以便可以将分组列与汇总列分开,并确保在内部查询中包含要聚合的列。
答案 1 :(得分:1)
您可以在没有子查询的情况下执行此操作:
SELECT
YEAR(o.OrderDate) AS [Year],
DATEPART(QUARTER, o.OrderDate) AS [Quarter],
CASE
WHEN SUBSTRING(od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END AS ProductLine,
SUM(od.QPrice * od.Quantity)
FROM Orders o
INNER JOIN Odetail od
ON o.OrderNum = od.OrderNum
WHERE
o.OrderDate >= CAST('20120101' AS DATE)
AND o.OrderDate < CAST('20130101' AS DATE)
GROUP BY
YEAR(o.OrderDate),
DATEPART(QUARTER, o.OrderDate),
CASE
WHEN SUBSTRING(od.PNum, 4, 1)= 'M' THEN 'Motors'
WHEN SUBSTRING(od.PNUM, 4, 1)= 'T' THEN 'Trolling Motors'
WHEN SUBSTRING(od.PNum, 4, 1)= 'P' THEN 'Pumps'
END
注意:避免使用旧式JOIN
语法。请阅读Aaron Bertrand的article。