在日期范围之间显示结果或在选择标准之间显示空值?
Show results between daterange or show null values between selection criteria?
我正在尝试获取 return 结果的报告,但目前得到 incorrect/inconsistent 结果,这让我有点头疼。
我正在使用的查询的一个非常简单的片段如下所示。
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
WHERE OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
如您所料,这会 return、客户名称和文档值在定义的日期范围内。但是,我还想包含也出现在日期范围内的 NULL
值?
(它背后的想法,是一个很好的简单报告,customer/spend 在一个日期范围内)。
如果我尝试 return NULL
值,它仅显示数据库中整个日期范围内的 NULL
值。有没有合理的方式让我获得这些信息?
编辑上面的数据,希望能解释我得到的结果和我想要实现的结果...我的销售价值来自 OINV.DocTotal,日期范围来自 OINV.DocDate...
使用以下数据;我假设我正在尝试显示“NULL”值或“2019”日期。
A) - 2018 年 - 销售额 100 英镑 | 2019 年 - 销售额 100 英镑 | 2020 年 - 销售额 100 英镑
以上显示的值为 100 英镑,因为 2019 年的销售额为 100 英镑。这太完美了,我希望数据会如何显示。
B) 2018 年 - NULL 销售额 | 2019 年 - NULL 销售额 | 2020 年 - 空销售额
以上将 return 一个“NULL”值;由于客户尚未消费,因此属于“NULL”类别。如上所述,这就是我希望 Null 数据显示的方式。
C) 2018 年 - 100 英镑销售额 | 2019 年 - NULL 销售额 | 2020 年 - £50 销售额
上面一行是我的问题;因为我的查询正在查找 2019 年的日期或 NULL 值,所以它根本没有显示任何内容。 (因为一个数据存在于我的日期范围之外,并且没有2019年范围内的值)这是否有意义?
--- 进一步编辑 ----
如下所示;在我的报告中,如果我将日期范围设置为 2019 年,则 2x 值“NULL”和“06/08/2018”将从我的报告中消失。就好像客户不存在一样。
我只是想让它表明它们确实存在,只是在 2019 年还没有购买。
对于“NULL”值,我假设您指的是 OCRD
中的所有行,即使没有匹配项也是如此。如果是这种情况,您可以使用 LEFT JOIN
:
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT JOIN
OINV
ON OCRD.CardCode = OINV.CardCode AND
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO';
注意:如果 'DATEFROM'
和 'DATETO'
是从应用程序传入的,您应该使用参数。您不应该使用参数值修改查询字符串。
如果我是正确的,NULL
可能在 DocDate
列中,并且您想将它们包含在结果集中。为此,您可以试试这个:
SELECT OCRD.CardName, ISNULL(OINV.DocTotal, 0) DocTotal
FROM OCRD
LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
WHERE ISNULL(OINV.DocDate, 'DATEFROM') >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
不是最干净的结果,但这是我设法为我工作的查询。我在其中添加了“类型”字段,这样您就可以看到我为每个查询尝试实现的结果。
SELECT 'Range' AS 'Type', T0.CardCode, T1.DocTotal, T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE T1.DocDate >= '2019-01-01' and T1.DocDate <= '2019-12-31'
UNION ALL
SELECT 'Null' AS 'Type', T0.CardCode, T1.DocTotal, T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE T1.DocDate IS NULL
UNION ALL
SELECT 'OutRange' AS ' Type', T0.CardCode, '0' AS 'DocTotal', T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE (T1.DocDate < '2019-01-01' OR T1.DocDate > '2019-12-31')
ORDER BY [TYPE]
`
如果将日期筛选器移到联接条件中,您将看到所需的结果。从不消费的客户将与消费超出预期范围的客户完全相同。
您会在整个 Stack Overflow 中看到这个特殊问题。它归结为对外部连接的内侧使用 where
子句。将条件移动到连接中会更改应用连接期间而不是之后应用的行为。
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
您也可以通过这种方式更明确地首先应用过滤器:
with FilteredInvoices as (
SELECT * FROM OINV
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
)
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN FilteredInvoices OINV ON
ON OCRD.CardCode = OINV.CardCode;
我正在尝试获取 return 结果的报告,但目前得到 incorrect/inconsistent 结果,这让我有点头疼。
我正在使用的查询的一个非常简单的片段如下所示。
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
WHERE OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
如您所料,这会 return、客户名称和文档值在定义的日期范围内。但是,我还想包含也出现在日期范围内的 NULL
值?
(它背后的想法,是一个很好的简单报告,customer/spend 在一个日期范围内)。
如果我尝试 return NULL
值,它仅显示数据库中整个日期范围内的 NULL
值。有没有合理的方式让我获得这些信息?
编辑上面的数据,希望能解释我得到的结果和我想要实现的结果...我的销售价值来自 OINV.DocTotal,日期范围来自 OINV.DocDate... 使用以下数据;我假设我正在尝试显示“NULL”值或“2019”日期。
A) - 2018 年 - 销售额 100 英镑 | 2019 年 - 销售额 100 英镑 | 2020 年 - 销售额 100 英镑
以上显示的值为 100 英镑,因为 2019 年的销售额为 100 英镑。这太完美了,我希望数据会如何显示。
B) 2018 年 - NULL 销售额 | 2019 年 - NULL 销售额 | 2020 年 - 空销售额
以上将 return 一个“NULL”值;由于客户尚未消费,因此属于“NULL”类别。如上所述,这就是我希望 Null 数据显示的方式。
C) 2018 年 - 100 英镑销售额 | 2019 年 - NULL 销售额 | 2020 年 - £50 销售额
上面一行是我的问题;因为我的查询正在查找 2019 年的日期或 NULL 值,所以它根本没有显示任何内容。 (因为一个数据存在于我的日期范围之外,并且没有2019年范围内的值)这是否有意义?
--- 进一步编辑 ----
如下所示;在我的报告中,如果我将日期范围设置为 2019 年,则 2x 值“NULL”和“06/08/2018”将从我的报告中消失。就好像客户不存在一样。 我只是想让它表明它们确实存在,只是在 2019 年还没有购买。
对于“NULL”值,我假设您指的是 OCRD
中的所有行,即使没有匹配项也是如此。如果是这种情况,您可以使用 LEFT JOIN
:
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT JOIN
OINV
ON OCRD.CardCode = OINV.CardCode AND
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO';
注意:如果 'DATEFROM'
和 'DATETO'
是从应用程序传入的,您应该使用参数。您不应该使用参数值修改查询字符串。
如果我是正确的,NULL
可能在 DocDate
列中,并且您想将它们包含在结果集中。为此,您可以试试这个:
SELECT OCRD.CardName, ISNULL(OINV.DocTotal, 0) DocTotal
FROM OCRD
LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
WHERE ISNULL(OINV.DocDate, 'DATEFROM') >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
不是最干净的结果,但这是我设法为我工作的查询。我在其中添加了“类型”字段,这样您就可以看到我为每个查询尝试实现的结果。
SELECT 'Range' AS 'Type', T0.CardCode, T1.DocTotal, T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE T1.DocDate >= '2019-01-01' and T1.DocDate <= '2019-12-31'
UNION ALL
SELECT 'Null' AS 'Type', T0.CardCode, T1.DocTotal, T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE T1.DocDate IS NULL
UNION ALL
SELECT 'OutRange' AS ' Type', T0.CardCode, '0' AS 'DocTotal', T1.DocDate
FROM OCRD T0 LEFT OUTER JOIN OINV T1 ON T1.CardCode = T0.CardCode
WHERE (T1.DocDate < '2019-01-01' OR T1.DocDate > '2019-12-31')
ORDER BY [TYPE]
`
如果将日期筛选器移到联接条件中,您将看到所需的结果。从不消费的客户将与消费超出预期范围的客户完全相同。
您会在整个 Stack Overflow 中看到这个特殊问题。它归结为对外部连接的内侧使用 where
子句。将条件移动到连接中会更改应用连接期间而不是之后应用的行为。
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN OINV ON OCRD.CardCode = OINV.CardCode
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
您也可以通过这种方式更明确地首先应用过滤器:
with FilteredInvoices as (
SELECT * FROM OINV
OINV.DocDate >= 'DATEFROM' AND OINV.DocDate <= 'DateTO'
)
SELECT OCRD.CardName, OINV.DocTotal
FROM OCRD LEFT OUTER JOIN FilteredInvoices OINV ON
ON OCRD.CardCode = OINV.CardCode;