Sql server 将大小写表达式用作列别名、总和、分组依据和子查询时出错

Sql server 将大小写表达式用作列别名、总和、分组依据和子查询时出错,sql-server,tsql,group-by,sum,case,Sql Server,Tsql,Group By,Sum,Case,我有两张桌子:Orders和ODetail。我想创建一个表,显示2012年的销售总额,按年份、季度和产品线(这是一种情况)分组。以下是我的SQL代码: SELECT * FROM (SELECT YEAR(o.OrderDate) 'Year', DATEPART(Quarter, o.OrderDate) 'Quarter', CASE WHEN SUBSTRING (od.PNum, 4, 1)= 'M'

我有两张桌子: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列之外的所有列进行分组时,查询工作正常。有什么想法吗

无需子查询即可执行此操作:

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
选择
年(订单日期)为[年],
日期部分(季度,o.OrderDate)为[季度],
案例
当子串(外径PNum,4,1)=‘M’时,则为‘马达’
当子串(外径PNUM,4,1)=“T”时,则为“牵引电机”
当子字符串(od.PNum,4,1)=“P”时,则为“泵”
作为产品线结束,
总额(外径价格*外径数量)
从命令
内连接尾外径
ON o.OrderNum=od.OrderNum
哪里
o、 订单日期>=CAST('20101'为日期)
和o.OrderDate


注意:避免使用旧式的
JOIN
语法。阅读Aaron Bertrand的文章。

无需子查询即可:

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
选择
年(订单日期)为[年],
日期部分(季度,o.OrderDate)为[季度],
案例
当子串(外径PNum,4,1)=‘M’时,则为‘马达’
当子串(外径PNUM,4,1)=“T”时,则为“牵引电机”
当子字符串(od.PNum,4,1)=“P”时,则为“泵”
作为产品线结束,
总额(外径价格*外径数量)
从命令
内连接尾外径
ON o.OrderNum=od.OrderNum
哪里
o、 订单日期>=CAST('20101'为日期)
和o.OrderDate


注意:避免使用旧式的
JOIN
语法。阅读Aaron Bertrand的文章。

无需子查询即可:

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
选择
年(订单日期)为[年],
日期部分(季度,o.OrderDate)为[季度],
案例
当子串(外径PNum,4,1)=‘M’时,则为‘马达’
当子串(外径PNUM,4,1)=“T”时,则为“牵引电机”
当子字符串(od.PNum,4,1)=“P”时,则为“泵”
作为产品线结束,
总额(外径价格*外径数量)
从命令
内连接尾外径
ON o.OrderNum=od.OrderNum
哪里
o、 订单日期>=CAST('20101'为日期)
和o.OrderDate


注意:避免使用旧式的
JOIN
语法。阅读Aaron Bertrand的文章。

无需子查询即可:

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
选择
年(订单日期)为[年],
日期部分(季度,o.OrderDate)为[季度],
案例
当子串(外径PNum,4,1)=‘M’时,则为‘马达’
当子串(外径PNUM,4,1)=“T”时,则为“牵引电机”
当子字符串(od.PNum,4,1)=“P”时,则为“泵”
作为产品线结束,
总额(外径价格*外径数量)
从命令
内连接尾外径
ON o.OrderNum=od.OrderNum
哪里
o、 订单日期>=CAST('20101'为日期)
和o.OrderDate


注意:避免使用旧式的
JOIN
语法。请阅读Aaron Bertrand的文章。

GROUP by
将通知将哪些列分组并应用于聚合函数,在本例中为
SUM
。如果你把你的内部查询(你的别名<代码> A/COD>)作为一个单独的查询,那就更容易看到错误了。然后,您将看到您有一个
总和
,但没有
分组依据

当您按
对列
年度、季度、产品线
进行分组时,您说的是“选择与年度、季度和产品线匹配的多行,然后将它们汇总,并将
价格*数量
的值相加”

因此,您可以将
分组依据
与内部查询放在一起:

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
注意:如果您的查询发生更改,列别名将发生更改,并且可能不太可维护,但对于临时查询来说效果很好

最后,您可以将
总和
移到外部,而不是将
组按
移到内部:

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

注意:您必须避免选择
*
,以便将分组列与聚合列分开,并确保将要聚合的列包含在内部查询中。

分组依据将通知哪些列被分组并应用于聚合函数,在本例中为
求和。如果你把你的内部查询(你的别名<代码> A/COD>)作为一个单独的查询,那就更容易看到错误了。然后,您将看到您有一个
总和
,但没有
分组依据

当您按
分组时,
年、季度、产品线
您在