【问题标题】:TSQL - exclude users who who meet ONLY criteriaTSQL - 排除仅满足条件的用户
【发布时间】:2021-05-14 06:52:13
【问题描述】:

目标是排除或以其他方式标记拥有 ItemNumber 记录(如“9%”)的客户。

    CustomerID  ItemNumber
    85610           99
    85611           11
    85611           99
    85612           13
    85612           11
    85612           98
    85613           98
    85613           99

在此示例中,应排除或标记 CustomerID 86510 和 86513,因为与其记录关联的唯一 ItemNumber 类似于“9%”。

我将不胜感激。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:
    SELECT CustomerID, ItemNumber
    FROM dbo.table AS t
    WHERE NOT EXISTS
    (
        SELECT 1
        FROM dbo.table 
        WHERE CustomerID = t.CustomerID 
        AND ItemNumber NOT LIKE '9%'
    );
    

    【讨论】:

    • +1 - 非常聪明。在相关说明中,在 EXISTS 上使用 SELECT 1 而不是表的真实列是否会提高性能?
    • @Lamak 不,没有性能差异。 SQL Server 知道 EXISTS 中的任何内容都不需要具体化。您可以放置​​ SELECT * 或 SELECT 任何列,它不会改变计划。我喜欢使用常量,因为读者很清楚这个子查询没有选择任何数据。
    • 我认为查询处理器会对列或 * 做一些工作,但生成的计划将是相同的,并且在执行时不会有任何差异。编译时差异可能不明显,但有些人有风格偏好。
    • 太棒了!工作就像一个魅力,写得非常清楚,很容易翻译成生产代码。太感谢了。另外,如何优雅地表达这个问题?我曾经,现在仍然不知所措。
    • 我不确定。我不知道能够将其表述为一个文字问题是多么有价值。如果您需要帮助解决您遇到的查询,我们会在样本数据和所需结果方面做得更好。单词问题通常会妨碍您。
    【解决方案2】:
    SELECT 
        CustomerID
    FROM Table T
    WHERE NOT EXISTS (SELECT CustomerID FROM Table WHERE CustomerId = T.CustomerId AND ItemNumber NOT LIKE '9%')
    

    【讨论】:

    • Aaron 用 ) 结束了他的查询;这正是我现在的感受。
    • 不过,这两个答案有一个关键的区别。 Aaron 正在使用 NOT LIKE '9%' 并且它是正确的,您正在使用 LIKE '9%' 并且不会按预期工作
    • 哦,+1,因为我是一名运动员,你的评论让我发笑。
    • 好吧,现在你的答案是对的 :-)。 @AaronBertrand - 是的,现在修复了
    • 是的,如果你喜欢,你可以对 +1 投反对票哈哈,我意识到你的实际上是正确的,因为我完全误读了。编辑:我指的是我如何过滤掉以“9%”开头的东西,而不是被问到的东西,它过滤掉了只有以“9%”开头的行的东西。
    【解决方案3】:

    另一种选择

    SELECT CustomerID
    FROM YourTable
    GROUP BY CustomerID
    HAVING MAX(CASE WHEN ItemNumber LIKE '9%' THEN 1 END) = 1
        AND MAX(CASE WHEN ItemNumber NOT LIKE '9%' THEN 1 END) IS NULL
    

    【讨论】:

    • 这里的缺点是,为了获得ItemNumbers,它需要再次靠在桌子上,对吧?如果不需要该列,这会比EXISTS 表现更好吗?
    • @Lamak - 这是对表格的一次扫描,所以可能是。如果不设置一些测试数据来比较两者并尝试索引和数据分布的不同组合,我不想猜测。
    • @Lamak - 对于 OP 的示例数据和下表定义 CREATE TABLE #YourTable (CustomerID INT, ItemNumber INT, PRIMARY KEY(CustomerID, ItemNumber)) 我得到 these plans and estimated costs.。摆脱索引和I get these plans and costs
    • 尽管没有索引,NOT EXISTS 计划正在重复进行全扫描,因此当表较大时该计划将开始变得相当昂贵,我猜该计划将需要更改为不同的连接类型并且优势可能会消失或被逆转(合并连接需要两种)
    【解决方案4】:
    create table tc(CustomerID int,ItemNumber varchar(10))
    
    INSERT INTO tc
    VALUES(85610,99),
        (85611,11),
        (85611,99),
        (85612,13),
        (85612,11),
        (85612,98),
        (85613,98),
        (85613,99)
    
    select CustomerID from tc 
    where ItemNumber like '9%'
    group by CustomerID 
    
    except
    
    select CustomerID from tc 
    where ItemNumber not like '9%'
    group by CustomerID 
    

    【讨论】:

      【解决方案5】:

      除非我遗漏了什么,否则为什么不只包含一个具有 ItemNumber NOT LIKE '9%'WHERE 子句

      【讨论】:

      • 是的,我认为你遗漏了一些东西。您的建议不起作用的原因是,简单的 where 子句将包括 ItemNumber 为 99,但在不同行中的 ItemNumber 也可能为 11 的客户。
      猜你喜欢
      • 2017-05-12
      • 2022-10-24
      • 1970-01-01
      • 2021-08-28
      • 2015-11-14
      • 2020-03-30
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多