Tsql 无法使缺失的天数显示为零

Tsql 无法使缺失的天数显示为零,tsql,outer-join,Tsql,Outer Join,这是我写的-我试图让没有事务的日期只显示字段的零。我去了谷歌,和我认识的每个人都谈过,这应该行得通——但不是: 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; DE

这是我写的-我试图让没有事务的日期只显示字段的零。我去了谷歌,和我认识的每个人都谈过,这应该行得通——但不是:

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    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
where子句实际上是将左连接更改为内部连接。 这是因为左连接为在右表中找不到的行返回null,而null与任何内容相比都将始终返回unknown,SQL Server将其解释为false

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

以下是除了DOCUMENT\u TYPE\u WID列(我不知道它属于哪个表)之外的代码的工作版本:

SELECT '10111' 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
        AND IT.BUSINESS_UNIT_WID = '837'
        AND IT.ITEM2_NUM = '10111'
        -- I had to guess where this column belongs, it might be on the BI table
        AND IT.DOCUMENT_TYPE_WID = 22
    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 D.Date >= DATEADD(yy, -1, GETDATE())
GROUP BY D.Date
ORDER BY D.Date DESC;

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;

请在代码问题中给出一个-cut&paste&runnable代码;示例输入,具有预期和实际输出,包括逐字错误消息;标签和版本;清晰的说明和解释。这包括您能给出的最少代码,即您显示为OK的代码,由您显示为not OK的代码扩展。调试基础。PS如果你不努力清楚地说出你想要什么,那么你就无法理解、推理、交流或搜索。使用足够多的单词、句子和引用部分示例,以清楚、完整地表达您的意思。了解返回时的左连接:行上的内部连接联合所有不匹配的左表行以null扩展。始终知道作为外部联接的一部分,您需要什么样的内部联接。上的WHERE或内部联接,在上的外部联接删除任何由NULL扩展的行后,要求右[sic]表列不为NULL,即在行上只保留内部联接,即将外部联接转换为内部联接。这是常见问题解答。在考虑发帖之前,请始终用谷歌搜索任何错误消息,以及你的问题/问题/目标的许多清晰、简洁和准确的措辞,有没有你的特定字符串、名称和行号,有没有“site:stackoverflow.com”,并阅读许多点击和答案。如果你发布一个问题,用一句话作为标题。请参阅文本上方的投票箭头鼠标(&S)。可能重复的
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;