【问题标题】:Possible correlation subqueries可能的相关子查询
【发布时间】:2023-03-20 21:40:01
【问题描述】:

我是子查询的新手,而相关性现在正试图理解一个问题。

我有一个问题:

SELECT Sales.SalesOrderHeader.CustomerID, SUM(Sales.SalesOrderDetail.LineTotal)
FROM Sales.SalesOrderDetail
    INNER JOIN Sales.SalesOrderHeader
    ON Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID
GROUP BY Sales.SalesOrderHeader.CustomerID;

我正在尝试使用子查询相关性重写查询:

SELECT Sales.SalesOrderHeader.CustomerID,
       (SELECT SUM(Sales.SalesOrderDetail.LineTotal)
        FROM Sales.SalesOrderDetail
        GROUP BY SalesOrderDetail.SalesOrderID)
FROM Sales.SalesOrderHeader
GROUP BY Sales.SalesOrderHeader.CustomerID;

我有以下错误,我不明白我需要修复什么:

子查询返回超过 1 个值。这是不允许的,当 子查询遵循 =、!=、、>= 或当子查询用作 一个表达式。

如果建议与原始查询相关的不同选项,那将是很好的。祝你有美好的一天。

【问题讨论】:

    标签: sql correlated-subquery


    【解决方案1】:

    为了您的理解,子查询必须为每一行返回一个值。你的代码:

    (SELECT SUM(Sales.SalesOrderDetail.LineTotal)
            FROM Sales.SalesOrderDetail
            GROUP BY SalesOrderDetail.SalesOrderID)
    

    将返回一个以上的值,因为您是按 SalesOrderDetail.SalesOrderID 分组的,结果集的行数将与表中不同的 SalesOrderDetail.SalesOrderID 一样多。

    所以你必须删除 group by 子句,它会起作用。否则,如果您想根据SalesOrderDetail.SalesOrderID 获得相应的值,那么您必须使用 jarlh 中的 where 子句回答:

    (SELECT SUM(SalesOrderDetail.LineTotal)
            FROM SalesOrderDetail
            WHERE SalesOrderDetail.SalesOrderID = SalesOrderHeader.SalesOrderID)
    

    这将为结果集提供每行一个值,该值使用SalesOrderDetail.SalesOrderID 过滤。

    希望你能理解。

    【讨论】:

    • 感谢您对情况的澄清。任何猜测为什么收到不同数量的行?
    • 哪个语句给出了不同的行数?
    • jarlh 答案 - 31465 行。原始查询 - 19119。
    【解决方案2】:

    在子查询中跳过 group by,改为添加相关性:

    SELECT Sales.SalesOrderHeader.CustomerID,
           (SELECT SUM(Sales.SalesOrderDetail.LineTotal)
            FROM Sales.SalesOrderDetail
            WHERE Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID)
    FROM Sales.SalesOrderHeader
    

    同样,使用表别名:

    SELECT soh.CustomerID,
           (SELECT SUM(sod.LineTotal)
            FROM Sales.SalesOrderDetail sod
            WHERE sod.SalesOrderID = soh.SalesOrderID)
    FROM Sales.SalesOrderHeader soh
    

    编辑:

    SELECT DISTINCT soh.CustomerID,
           (SELECT SUM(sod.LineTotal)
            FROM Sales.SalesOrderDetail sod
            WHERE sod.SalesOrderID = soh.SalesOrderID)
    FROM Sales.SalesOrderHeader soh
    

    执行SELECT DISTINCT 删除重复行,并返回与GROUP BY 版本相同的结果。

    【讨论】:

    • 它变成了 31465 行 19119。
    • 如果有兴趣,可以在这里下载数据库。 msftdbprodsamples.codeplex.com/downloads/get/880661
    • 收到 31349 行。
    • 我明白了,Sales.SalesOrderDetail 表中有没有引用的 Sales.SalesOrderHeader 行。子查询版本实际上更多的是 LEFT JOIN 而不是 INNER JOIN。你想要那些行吗?
    • 是的,它们是必需的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多