不能错过的日子显示为零

时间:2019-08-20 17:20:54

标签: tsql outer-join

这是我写的-我试图获取不包含交易的日期,仅将字段显示为零。我已经去了Google并与我认识的所有人进行了交谈,这应该可以工作-但不是:?

IF OBJECT_ID('tempdb..#D') IS NOT NULL
    DROP TABLE #D;

CREATE TABLE #D
(
    [Date] [DATE] NOT NULL,
    PRIMARY KEY CLUSTERED ([Date] ASC)
);

DECLARE @CurrentDate DATE = GETDATE() - 95;
DECLARE @EndDate DATE = GETDATE();

WHILE @CurrentDate < @EndDate
BEGIN
    INSERT INTO #D
    (
        [Date]
    )
    SELECT DATE = @CurrentDate;
    SET @CurrentDate = DATEADD(DD, 1, @CurrentDate);
END;

--SELECT * FROM #D ORDER BY  Date DESC


SELECT ITEM2_NUM AS 'Part Number',
       COALESCE(SUM(TRANS_QTY), 0) 'Daily Usage',
       D.Date AS 'Usage Date'
FROM #D AS D
    LEFT OUTER JOIN dbo.W_INVENTORY_TRANS_F IT
        ON IT.GL_DT = D.Date
    LEFT JOIN dbo.W_BU_ITEM_D BI
        ON BI.BUSINESS_UNIT_WID = IT.BUSINESS_UNIT_WID
           AND BI.ITEM_WID = IT.ITEM_WID
WHERE DOCUMENT_TYPE_WID = 22
      AND D.Date >= DATEADD(yy, -1, GETDATE())
      AND IT.BUSINESS_UNIT_WID = '837'
      AND IT.ITEM2_NUM = '10111'
      AND BI.STOCKING_TYPE = 'P'
GROUP BY ITEM2_NUM,
         D.Date
ORDER BY D.Date DESC;

以下是我得到的结果:

Part Number Daily Usage Usage Date
10111   -331.0000   2019-08-19
10111   -2617.0000  2019-08-16
10111   -418.0000   2019-08-15
10111   -471.0000   2019-08-14
10111   -1158.0000  2019-08-13
10111   -766.0000   2019-08-12
10111   -1385.0000  2019-08-09

这就是我想要的:

Part Number Daily Usage Usage Date
10111   -331    8/19/2019
10111     0     8/18/2019
10111     0     8/17/2019
10111   -2617   8/16/2019
10111   -418    8/15/2019
10111   -471    8/14/2019
10111   -1158   8/13/2019
10111   -766    8/12/2019
10111     0     8/11/2019
10111     0     8/10/2019
10111   -1385   8/9/2019

2 个答案:

答案 0 :(得分:2)

您的where子句有效地将您的left join更改为inner join。 这是因为left join对于在右表中找不到的行返回空值,而null与任何内容相比将始终返回unknown,而SQL Server将其解释为{ {1}}。

您需要做的是将所有引用右侧表的条件移到false子句中。
另外,您正在按on分组,这没有意义,因为它已经在ITEM2_NUM子句中过滤掉了。

这是您的代码的有效版本(where列除外,我不知道它属于哪个表):

DOCUMENT_TYPE_WID

答案 1 :(得分:0)

Zohar是100%正确的-如果最终我使用的是最终代码,那么对于那些在下面某个时间点结束的人来说。

IF OBJECT_ID('tempdb..#D') IS NOT NULL
    DROP TABLE #D;

CREATE TABLE #D
(
    [Date] [DATE] NOT NULL,
    PRIMARY KEY CLUSTERED ([Date] ASC)
);

DECLARE @CurrentDate DATE = GETDATE() - 95;
DECLARE @EndDate DATE = GETDATE();

WHILE @CurrentDate < @EndDate
BEGIN
    INSERT INTO #D
    (
        [Date]
    )
    SELECT DATE = @CurrentDate;
    SET @CurrentDate = DATEADD(DD, 1, @CurrentDate);
END;

IF OBJECT_ID('tempdb..#DailyUsage') IS NOT NULL
    DROP TABLE #DailyUsage;

CREATE TABLE #DailyUsage
(
    BU_ITEM_WID INT,
    TRANS_QTY DECIMAL(15, 4),
    GL_DT DATETIME
);
INSERT INTO #DailyUsage
(
    BU_ITEM_WID,
    TRANS_QTY,
    GL_DT
)
SELECT BU_ITEM_WID,
       TRANS_QTY AS 'Daily Usage',
       GL_DT
FROM dbo.W_INVENTORY_TRANS_F
WHERE 1 = 1
      AND DOCUMENT_TYPE_WID = 22
      AND GL_DT >= GETDATE() - 95;

CREATE NONCLUSTERED INDEX [IX_DailyUsage]
ON #DailyUsage (BU_ITEM_WID)
INCLUDE
(
    TRANS_QTY,
    GL_DT
);

WITH cte_ItemNums
AS (SELECT DISTINCT
        IT.ITEM2_NUM,
        IT.BU_ITEM_WID
    FROM W_INVENTORY_TRANS_F IT
        LEFT JOIN dbo.W_BU_ITEM_D BI
            ON BI.BUSINESS_UNIT_WID = IT.BUSINESS_UNIT_WID
               AND BI.ITEM_WID = IT.ITEM_WID
               AND BI.STOCKING_TYPE = 'P'
    WHERE 1 = 1
          AND IT.DOCUMENT_TYPE_WID = 22
          AND IT.BUSINESS_UNIT_WID = '837'
   )
SELECT IT1.ITEM2_NUM,
       COALESCE(SUM(IT2.TRANS_QTY), 0) AS 'Daily Usage',
       D.Date AS 'Usage Date'
FROM #D AS D
    LEFT OUTER JOIN cte_ItemNums IT1
        ON 1 = 1
    LEFT OUTER JOIN #DailyUsage IT2
        ON IT2.GL_DT = D.Date
           AND IT1.BU_ITEM_WID = IT2.BU_ITEM_WID
GROUP BY IT1.ITEM2_NUM,
         D.Date;