【问题标题】:SQLZoo Hard Questions #12 AdventureWorks AssessmentsSQLZoo 难题 #12 AdventureWorks 评估
【发布时间】:2013-12-13 01:09:17
【问题描述】:

我是数据库界的菜鸟,刚开始学习,发现 SQLZoo 网站对我很有帮助。 我在 AdventureWorks 数据库中遇到了这个问题。

http://sqlzoo.net/wiki/AdventureWorks_hard_questions

12.对于每个订单显示 SalesOrderID 和 SubTotal 的三种计算方式: A) 从 SalesOrderHeader B) OrderQty*UnitPrice 的总和 C) OrderQty*ListPrice 的总和

由于某种原因,我无法弄清楚这一点。非常感谢任何帮助。

这是我的查询:

SELECT 
   A.SalesOrderID,
   A.SubTotal AS SubTotalA,
   B.SubtotalB,
   C.SubtotalC 
FROM SalesOrderHeader A
JOIN
(
   SELECT SUM(sodB.OrderQty*sodB.UnitPrice) AS SubTotalB 
   FROM SalesOrderDetail sodB 
   JOIN ProductAW pawB 
   ON pawB.ProductID=sodB.ProductID
   GROUP BY sodB.SalesOrderID
)  AS B
JOIN
(
   SELECT SUM(sodC.OrderQty*pawC.ListPrice) AS SubTotalC 
   FROM SalesOrderDetail sodC 
   JOIN ProductAW pawC 
   ON pawC.ProductID=sodC.ProductID
   GROUP BY sodC.SalesOrderID
 )  AS C

由于某种原因,当我在 JOIN 之外单独运行 SELECT 语句 B 或 C 时,我得到了我期望的结果,但是当我将其放入 JOIN 时,SubTotalB 或 Subtotal C 的所有值都重复显示与第一行相同的结果价值。

SELECT SUM(sodC.OrderQty*pawC.ListPrice) AS SubTotalC 
   FROM SalesOrderDetail sodC 
   JOIN ProductAW pawC 
   ON pawC.ProductID=sodC.ProductID
   GROUP BY sodC.SalesOrderID

SELECT SUM(sodC.OrderQty*pawC.ListPrice) AS SubTotalC 
   FROM SalesOrderDetail sodC 
   JOIN ProductAW pawC 
   ON pawC.ProductID=sodC.ProductID
   GROUP BY sodC.SalesOrderID

【问题讨论】:

    标签: sql select join group-by


    【解决方案1】:

    这是最终的解决方案:

    SELECT 
       A.SalesOrderID,
       A.SubTotal AS SubTotalA,
       B.SubtotalB,
       C.SubtotalC 
    FROM SalesOrderHeader A
    JOIN
    (
       SELECT SUM(sodB.OrderQty*sodB.UnitPrice) AS SubTotalB, sodB.SalesOrderID 
       FROM SalesOrderDetail sodB 
       JOIN ProductAW pawB 
       ON pawB.ProductID=sodB.ProductID
       GROUP BY sodB.SalesOrderID
    )  AS B
    ON A.SalesOrderID = B.SalesOrderID
    JOIN
    (
      SELECT SUM(sodC.OrderQty*pawC.ListPrice) AS SubTotalC, sodC.SalesOrderID 
      FROM SalesOrderDetail sodC 
      JOIN ProductAW pawC 
      ON pawC.ProductID=sodC.ProductID
      GROUP BY sodC.SalesOrderID
    )  AS C
    ON A.SalesOrderID = C.SalesOrderID
    

    【讨论】:

      【解决方案2】:

      您的外部查询没有任何 ON 子句。这将导致表 B 中的每条记录都针对表 A 中的每条记录进行设置。因此,如果表 A 有 5 条记录,而表 B 有 5 条记录,那么您总共有 25 条记录。然后,当然所有这些记录也会与表 C 相乘。所有 AB 记录都将针对表 C 中的每条记录进行设置。

      我在每个子查询的 SELECT 语句中添加了一个 ProductID,然后在外部查询中的每个 JOINS 中添加了一个 ON 语句,以连接匹配的 ProductID。我希望这就是你想要的。

      SELECT 
         A.SalesOrderID,
         A.SubTotal AS SubTotalA,
         B.SubtotalB,
         C.SubtotalC 
      FROM SalesOrderHeader A
      JOIN
      (
         SELECT SUM(sodB.OrderQty*sodB.UnitPrice) AS SubTotalB,
         pawB.ProductID
         FROM SalesOrderDetail sodB 
         JOIN ProductAW pawB 
         ON pawB.ProductID=sodB.ProductID
         GROUP BY sodB.SalesOrderID
      )  AS B 
      ON A.ProductID = B.ProductID
      JOIN
      (
         SELECT SUM(sodC.OrderQty*pawC.ListPrice) AS SubTotalC,
         pawC.ProductID
         FROM SalesOrderDetail sodC 
         JOIN ProductAW pawC 
         ON pawC.ProductID=sodC.ProductID
         GROUP BY sodC.SalesOrderID
       )  AS C
      ON A.ProductID = C.ProductID
      

      【讨论】:

      • 在您指出外部查询缺少 ON 子句之后,我还意识到 B 和 C 查询缺少对其 SalesOrderID 的引用。我将 sob.SalesOrderID 和 sodC.SalesOrderID 添加到您的解决方案中,现在它可以工作了!非常感谢
      【解决方案3】:

      我喜欢那个网站,但我希望有一个地方可以比较答案,因为我只想知道我的查询是否以最佳方式完成。这是我为同样的问题想出的:

      SELECT soh.salesorderid, soh.subtotal AS "SubTotal A", SUM(sod.orderqty * sod.unitprice) AS "SubTotal B", SUM(sod.orderqty * paw.ListPrice) AS "SubTotal C" FROM SalesOrderHeader soh JOIN SalesOrderDetail sod (ON sod.salesorderid = soh.salesorderid) JOIN ProductAW paw (ON paw.productid = sod.productid) GROUP BY soh.salesorderid

      我还在学习,所以如果有人想插话并告诉我如何改进它,请这样做。

      【讨论】:

        【解决方案4】:

        我们可以使用聚合函数和 GROPING 来实现结果。使用 MAX(Soh.SubTotal) 考虑到 SalesOrderHeader 表中只有一个唯一行。其余的计算可以在聚合函数中完成。

        SELECT Soh.SalesOrderID
             , MAX(Soh.SubTotal) as SubTotal
             , COALESCE(SUM(Sod.OrderQty * Sod.UnitPrice), 0) as [Sum of OrderQty*UnitPrice]
             , COALESCE(SUM(Sod.OrderQty * Prd.ListPrice),0) as [Sum of OrderQty*ListPrice] 
        FROM   SalesOrderHeader as Soh 
               INNER JOIN SalesOrderDetail as Sod ON (Soh.SalesOrderID = Sod.SalesOrderID)
               INNER JOIN Product as Prd ON (Prd.ProductID = Sod.ProductID)
        GROUP BY Soh.SalesOrderID;
        

        【讨论】:

          【解决方案5】:

          这是正确答案:

          select soh.salesOrderId,soh.SubTotal,sum(sod.OrderQty*sod.UnitPrice), 
          sum(sod.OrderQty*p.ListPrice) from SalesOrderHeader soh
          inner join SalesOrderDetail sod on soh.SalesOrderId=sod.SalesOrderId
          inner join Product p on p.ProductId=sod.productId
          group by soh.salesOrderId,soh.SubTotal;
          

          投票最多的答案是:

          1. 过于复杂
            • 不需要子查询,它们只是使查询的读取时间更长
          2. 性能更差
            • 重复访问同一个表以搜索相同的行,只是处理方式不同。
          3. 不再适用于冒险作品。
            • 没有名为“ProductAw”的表,现在是“Product”,我猜他们会更改它

          此解决方案与 @Vishwanath Dalvi 使用合并的减号相同,因为它不需要。 也与@AruN 相同,这实际上只是对他的回答的评论的回应(要求提供理由)所以这应该是对他的回答的评论。 不幸的是,我刚开始使用 stackOverflow,无法发表评论:(

          【讨论】:

            【解决方案6】:
            select t1.SalesOrderID ID,t1.SubTotal SUBTOTAL,
            sum(t2.OrderQty*t2.UnitPrice) SUBTOTAL
            ,sum(t2.OrderQty*t3.ListPrice) SUBTOTAL
            from SalesOrderHeader t1 join SalesOrderDetail t2 on t1.SalesOrderID=t2.SalesOrderID join ProductAW t3 on t3.productid=t2.productid
            group by t1.SalesOrderID,t1.Subtotal
            

            【讨论】:

            • 请编辑您的答案。将您的代码添加到代码标签中以获得更好的可读性,并添加说明您做了什么以及为什么以及如何解决 OP 的问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-07-27
            • 1970-01-01
            • 2013-07-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-04
            相关资源
            最近更新 更多