子查询没有返回正确的结果T-SQL

时间:2013-03-15 16:14:56

标签: sql-server tsql

我有一个Subquery没有返回我正在寻找的结果。在最后一个子查询中,我有3个部件在我的条件下没有日期范围的订单计数,他们没有返回结果为0.而是我丢失了这些部分的所有其他数据。我确信有更好的查询数据的方法,所以这是我的查询。

    SELECT b.Part, b.Last_12_Mo, b.Last_6_Mo,
       COUNT(sd.SBINV) AS Order_Count
  FROM (
        SELECT a.Part, a.Last_12_Mo,
               ISNULL(SUM(sd.SBQSHP), 0) AS Last_6_Mo
          FROM (
                SELECT t3.Part, ISNULL(SUM(sd.SBQSHP),0) AS Last_12_Mo
                  FROM Top300 AS t3
                  LEFT JOIN SalesData AS sd 
                    ON t3.Part   = sd.SBITEM
                   AND sd.SBINDT > '20120315'
                 GROUP BY t3.Part, sd.SBLOC
                ) AS a 
          LEFT JOIN SalesData AS sd
            ON a.Part       = sd.SBITEM
           AND sd.SBINDT    > '20121015'
         GROUP BY a.Part, a.Last_12_Mo
        ) AS b 
  LEFT JOIN SalesData AS sd
    ON b.Part       = sd.SBITEM
   AND sd.SBINDT    > '20130110'
 GROUP BY b.Part, b.Last_12_Mo, b.Last_6_Mo
 ORDER BY b.Part

1 个答案:

答案 0 :(得分:0)

你走了。这应该做到这一点。

  • 由于您始终希望Top300中的所有项目与销售数据无关,因此您始终必须将每个子查询的结果保留在LEFT JOIN的左侧。
  • 您可以将NULL SUM聚合解析为零
  • 日期过滤器需要位于JOIN中,因为您不希望限制未加入的Top300项目。如果将它们放在WHERE子句中,那么它将排除未与销售数据连接的Top300项目,因为这些记录的日期将为NULL。

首先设置测试表和数据

    IF OBJECT_ID('Top300', 'U') IS NOT NULL DROP TABLE Top300;
    GO
    IF OBJECT_ID('SalesData', 'U') IS NOT NULL DROP TABLE SalesData;
    GO
    CREATE TABLE Top300 (
        Part  varchar(10)
    )
    GO
    CREATE TABLE SalesData (
        SBITEM  varchar(10)
       ,SBQSHP  int
       ,SBINV   int
       ,SBINDT  int
    )
    GO

    INSERT Top300
    SELECT A.*
      FROM (
            SELECT * FROM Top300 WHERE 1=2
            UNION ALL SELECT 'Widget1'
            UNION ALL SELECT 'Widget2'
            UNION ALL SELECT 'Widget3'
            UNION ALL SELECT 'Widget4'
            UNION ALL SELECT 'Widget5'
            UNION ALL SELECT 'Widget6'
           ) A

    INSERT SalesData
    SELECT A.*
      FROM (
            SELECT * FROM SalesData WHERE 1=2
            UNION ALL SELECT 'Widget1', 100, 1000, '20120316'
            UNION ALL SELECT 'Widget2', 100, 1000, '20120316'

            UNION ALL SELECT 'Widget3', 100, 1000, '20121016'
            UNION ALL SELECT 'Widget4', 100, 1000, '20121016'
            UNION ALL SELECT 'Widget5', 100, 1000, '20121016'
           ) A

现在让我们运行原始查询的更正版本

    SELECT b.Part, b.Last_12_Mo, b.Last_6_Mo,
           COUNT(sd.SBINV) AS Order_Count
      FROM (
            SELECT a.Part, a.Last_12_Mo,
                   ISNULL(SUM(sd.SBQSHP), 0) AS Last_6_Mo
              FROM (
                    SELECT t3.Part, ISNULL(SUM(sd.SBQSHP),0) AS Last_12_Mo
                      FROM Top300 AS t3
                      LEFT JOIN SalesData AS sd 
                        ON t3.Part   = sd.SBITEM
                       AND sd.SBINDT > '20120315'
                     GROUP BY t3.Part
                    ) AS a 
              LEFT JOIN SalesData AS sd
                ON a.Part       = sd.SBITEM
               AND sd.SBINDT    > '20121015'
             GROUP BY a.Part, a.Last_12_Mo
            ) AS b 
      LEFT JOIN SalesData AS sd
        ON b.Part       = sd.SBITEM
       AND sd.SBINDT    > '20130110'
     GROUP BY b.Part, b.Last_12_Mo, b.Last_6_Mo
     ORDER BY b.Part

最后,让我们运行一个更简单,更优化的查询,产生相同的结果

    SELECT b.Part
          ,SUM(CASE WHEN sd.SBINDT > '20120315' THEN sd.SBQSHP ELSE 0 END) as [Last_12_Mo]
          ,SUM(CASE WHEN sd.SBINDT > '20121015' THEN sd.SBQSHP ELSE 0 END) as [Last_6_Mo]
          ,SUM(CASE WHEN sd.SBINDT > '20130110' THEN 1 ELSE 0 END) as [Order_Count]
      FROM Top300 b
      LEFT JOIN SalesData AS sd
        ON b.Part       = sd.SBITEM
       AND sd.SBINDT    > '20120315'
     GROUP BY b.Part
     ORDER BY b.Part