【问题标题】:3 sets of paired exclusion criteria3组配对排除标准
【发布时间】:2020-11-09 23:04:47
【问题描述】:

我有一份订单清单。

我的表中有一个“保留”列,其中包含连接的保留代码。

我想返回所有行,包括价格为“0.01”的行,除非价格为“0.01”的行在 OnHold 列的正文中具有 3 个保留代码之一。

我试图以这种方式接近它:

Select *

From Table

Where NOT (Price='0.01' AND onhold LIKE '%Pricing Hold%') 

AND NOT (Price='0.01' AND  onhold LIKE '%Program  Hold%') 

AND NOT (Price='0.01' AND  onhold LIKE '%Program Hold%')

这不包括价格为“0.01”的所有内容,包括我拥有的价格=“0.01”且 onhold=Null 的行。这让我相信我试图用括号进行的分组不起作用。

我怎样才能拥有 3 组配对标准?

更新:所以,为了解决问题,我更新了查询只是为了说:

如果不是 ( onhold LIKE '%Pricing Hold%' onhold LIKE '%Program Hold%' onhold LIKE '%Program Hold%' )

返回的只是 1 条保留值为“.New:Line Hold”的记录,但不是保留值为 Null 的记录。所以现在我开始思考我是如何使用“NOT LIKE '%%'”的,它用空白的“onhold”来抑制行。

【问题讨论】:

  • 您更新的查询在语法上不正确,将产生错误而不是返回任何行。但是您的查询对您的数据非常敏感,因此强烈建议您发布MCVE。在更新之前您从未提及 NULL - NULL 永远不等于也不等于其他任何东西。这是编写 tsql 时要学习的一个重要概念。
  • 注意@Smor 他在原始问题中确实提到了 NULL:“这不包括价格为 '0.01' 的所有东西,包括我在价格 ='0.01' 和 onhold= 处的行空。”确实,我相信onhold=NULL 是唯一的情况 OP 的查询不起作用 - 这是这个问题的核心问题。

标签: sql sql-server string where-clause sql-like


【解决方案1】:

我想返回所有行,包括价格为“0.01”的行,除非价格为“0.01”的行在 OnHold 列的正文中具有 3 个保留代码之一。

你可以这样表述:

WHERE NOT (
    Price = 0.01
    AND (
        onhold LIKE '%Pricing Hold%' 
        OR onhold LIKE '%Program  Hold%'
        OR onhold LIKE '%Program Hold%'
    )
)

或者,假设Price 中没有NULL 值:

WHERE 
    Price <> 0.01
    OR (
        onhold NOT LIKE '%Pricing Hold%' 
        AND onhold NOT LIKE '%Program  Hold%'
        AND onhold NOT LIKE '%Program Hold%'
    )
)

我删除了 '0.01' 周围的单引号:Price 看起来像一个数值,所以它应该按原样存储(如果不是这样,你可以恢复它)。

【讨论】:

  • 我按照您的第一个示例进行了重组。但这不是灵丹妙药。它最终与尝试通过“NOT LIKE '%%'”逻辑处理 NULL 保留值有关。当我将其重构为“不(当 onhold 为 null 时的情况,然后 'No Hold' else onhold end like '%Pricing Hold%'”以确保我将非空字符串传递给评估时,它按预期运行。
  • 持有它——这个答案不能正确处理 NULL(戈登也不能)——而我的可以——​​但这就是答案吗?您的整个问题是如何处理 NULL。
  • 对不起,伙计。我在查询方面寻求帮助,你教了我如何制作临时表。您的解决方案对我没有帮助,但 GMB 建议的重组帮助我进行故障排除和隔离根本原因,我在没有临时表的情况下修复了这些问题。抱歉,GMB 提供了更多帮助。
【解决方案2】:

据我所知,您希望排除的唯一行是那些价格 = 0.01 并且值 onhold 是三个喜欢之一的行。

在下面的示例数据中,结果中应仅排除第一行

CREATE TABLE #Test (price decimal(10,2), onhold varchar(30));
INSERT INTO #Test (price, onhold)
VALUES                   -- DESIRED RESULT
(0.01, 'Pricing Hold'),  -- Not included
(0.02, 'Pricing Hold'),  -- Included
(0.01, NULL),            -- Included
(0.01, 'No hold'),       -- Included
(0.02, NULL);            -- Included

在您的代码中,第三行 0.01, NULL 不包括在内。

一种方法是对上述内容进行调整,以明确包含/允许 NULLS,例如,

SELECT  *
FROM    #Test
WHERE   Price <> 0.01 OR Price IS NULL
        OR onhold IS NULL
        OR NOT (
            onhold LIKE '%Pricing Hold%'
            OR onhold LIKE '%Program  Hold%'
            OR onhold LIKE '%Program Hold%'
            );

您也可以使用 EXCEPT 子句 - 它更具可读性但可能效率较低

SELECT  *
FROM    #Test
  EXCEPT
SELECT  *
FROM    #Test
WHERE   Price = 0.01
        AND (onhold LIKE '%Pricing Hold%'
            OR onhold LIKE '%Program  Hold%'
            OR onhold LIKE '%Program Hold%'
        );

以上都返回以下

price   onhold
0.01    NULL
0.01    No hold
0.02    NULL
0.02    Pricing Hold

这是db<>fiddle 我的结果。值得检查其他答案如何处理 NULL 值。

【讨论】:

  • 你似乎真的在获得解决方案标记上投入了精力,而且你在技术上是正确的,你认为 NULL 是问题的根源,即使你确实提供了一个比我实际可以更迂回的答案实施。
  • 谢谢 - 但我在你回答“这个帮助我......”后停下来,因为就是这样。后来的正确答案可能不如早期的引发思考的答案有用。我建议将其移回,或者至少支持 GMB 的答案。 GMB 和 Gordon 都错误地处理了 NULL 的事实表明需要小心处理它们。
【解决方案3】:

我认为这是逻辑:

Where Price = '0.01' AND
      onhold NOT LIKE '%Pricing Hold%' AND
      onhold NOT LIKE '%Program  Hold%' AND
      onhold NOT LIKE '%Program Hold%'

我建议Price = 0.01。如果您将price 存储为字符串,则应修复数据模型,以便将值存储为数字(可能是decimal/numeric)。

【讨论】:

    猜你喜欢
    • 2020-09-25
    • 1970-01-01
    • 2021-05-11
    • 2012-03-22
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2015-08-27
    • 2018-08-06
    相关资源
    最近更新 更多