【问题标题】:SELECT Records From Child Table That Are Not In Another And Parent Has No Other Children从不在另一个子表中的子表中选择记录,并且父级没有其他子级
【发布时间】:2020-01-08 16:39:18
【问题描述】:

我正在尝试编写一个查询来选择子表中的所有孤立记录,但仅当孤立记录是表中的唯一项目时。

我有两个来自不同系统的独立数据库,因此我无法使用外键强制引用完整性约束。每个的简单架构如下:

ITEMS
Order  |  Item
----------------
1      |   A1
1      |   A2
2      |   A1

COMP
Item
-------
A2

以上述数据为例,我想要一个返回 Order 2 的查询,因为父项上唯一可用的项目已被删除。

到目前为止,我有以下查询为我返回所有孤立的记录,包括订单 1。

SELECT Order FROM Items as i LEFT JOIN Comp as c ON i.Item = c.Item WHERE c.Item IS NULL

有什么想法吗?

【问题讨论】:

    标签: sql sql-server tsql sql-server-2008-r2


    【解决方案1】:

    当我创建两个表并输入数据时,这里是查询和结果

    CREATE TABLE Items(
      [Order] int,
      Item varchar(50)
    );
    
    CREATE TABLE Comp(
      Item varchar(50)
    );
    
    INSERT Items ([Order],Item)
    VALUES (1, 'A1');
    INSERT Items ([Order],Item)
    VALUES (1, 'A2');
    INSERT Items ([Order],Item)
    VALUES (2, 'A1');
    
    INSERT Comp (Item)
    VALUES('A2');
    
    
    
    
    SELECT i.[Order], i.Item 
    FROM Items as i 
    LEFT JOIN Comp as c ON i.Item = c.Item 
    WHERE c.Item IS NULL
    
    Order   Item
    1       A1
    2       A1
    

    【讨论】:

    • 来自 OP:“以上述数据为例,我想要一个返回 Order 2 的查询,因为父项上唯一可用的项目已被删除。”订单 1 不应包含在结果中,因为它的至少一项在 Comp 中。
    【解决方案2】:

    如果您在having count(distinct [Item]) = 1 条件下group by [Order] 表ITEMS,您将获得所有订单,其中只有一件商品。
    然后使用NOT EXISTS 检查COMP 中是否存在这些订单,或者像您的查询一样使用左连接:

    select i.[Order] from ITEMS i
    where i.[Order] IN (
      select [Order] from ITEMS
      group by [Order]
      having count(distinct [Item]) = 1
    )
    and not exists (select 1 from COMP where [Item] = i.[Item])
    

    或者:

    select i.[Order] 
    from ITEMS i left join COMP c
    on c.[Item] = i.[Item]
    where i.[Order] IN (
      select [Order] from ITEMS
      group by [Order]
      having count(distinct [Item]) = 1
    )
    and c.[Item] is null
    

    请参阅demo。

    【讨论】:

      【解决方案3】:

      您的查询即将完成:

      SELECT i.Order 
      FROM 
        Items as i 
        LEFT JOIN Comp as c 
        ON i.Item = c.Item 
      GROUP BY i.Order
      HAVING COUNT(c.Item) = 0
      

      此查询查找与订单相关的每个 c.Item 为空的所有订单

      左加入后你的数据看起来像:

      i.Order | i.Item | c.Item
      1       |   A1   |  null
      1       |   A2   |  A2
      2       |   A1   |  null
      

      对 c.Item 进行分组和计数;

      i.Order | i.Item | COUNT(c.Item)
      1       |   A1   |  1
      2       |   A1   |  0
      

      因为 count 向上计数,所以 null 的步长为 0,任何非 null 的步长为 1

      我们想要 HAVING 给我们的 i.Order=2 行; HAVING 是在分组完成后应用的 where 子句。 (WHERE 子句在分组之前应用,不能用于此)

      因此,此查询会查找其所有 c.Items 均为 NULL 的每个订单

      【讨论】:

      • 很好的解决方案!我考虑过使用聚合,但忘记了 NULL 值没有贡献!谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多