【问题标题】:Get all rows from table A where no matching row exist in table B从表 A 中获取表 B 中不存在匹配行的所有行
【发布时间】:2015-10-16 10:17:54
【问题描述】:

抱歉,我不太确定这个标题的标题是什么,我认为它比听起来要复杂一些。此问题适用于 Microsoft SQL Server 2008。

我有两个如下所示的表:

Logging.Logs:

+---------+------------+--------------+
|  LogID  |  LogEntry  |  LogTimeUtc  |
+---------+------------+--------------+
|  1      |  Foo       |  2015-10-16..|
|  2      |  Bar       |  2015-10-16..|
|  ...    |  ...       |  ...         |

Logging.LogAttributes:

+---------+------------------+----------------+
|  LogID  |  LogAttributeID  |  LogAttribute  |
+---------+------------------+----------------+
|  1      |  1               |  FooAttribute  |
|  1      |  2               |  BarAttribute  |
|  1      |  3               |  BazAttribute  |
|  2      |  1               |  FooAttribute  |
|  2      |  2               |  BazAttribute  |
|  ...    |  ...             |  ...           |

我想要来自 Logging.Logs 的所有 LogID,这些 LogID 在 Logging.LogAttributes 中没有对应的条目,LogAttribute 字段以“Bar”开头。

在上面的表格中,我只会得到 LogID 2,因为 LogID 1 在 LogAttributes 中有一行,LogAttribute 字段中有“BarAttribute”。

我从左连接开始,但它返回 1 和 2,因为 LogAttributes 中有 LogID 为 1 且 LogAttribute 不以 'Bar' 开头的条目

SELECT *
FROM Logging.Logs l
LEFT JOIN Logging.LogAttributes la
ON ( l.LogID = la.LogID AND la.LogAttribute NOT LIKE 'Bar%' )

【问题讨论】:

  • LogAttributes.LogID 可以为空吗?

标签: sql sql-server sql-server-2008 join


【解决方案1】:

您需要修改您的 JOIN 语句:

SELECT l.*
FROM Logging.Logs l
LEFT JOIN Logging.LogAttributes la ON l.LogID = la.LogID AND la.LogAttributeID LIKE 'Bar%'
WHERE la.LogID IS NULL

使用适当的索引,它应该比EXISTSIN 查询快很多

SQL Fiddle

【讨论】:

    【解决方案2】:

    你可以试试:

    SELECT *
    FROM Logging.Logs l
    WHERE NOT EXISTS 
         (SELECT * 
          FROM Logging.LogAttributes la 
          WHERE l.LogID = la.LogID AND la.LogAttribute LIKE 'Bar%' )
    

    【讨论】:

    • 所有答案都很好,谢谢,这个使用了我认为更好的 NOT EXISTS,所以我选择了这个作为接受的答案
    【解决方案3】:

    你应该这样做:

    SELECT *
    FROM Logging.Logs L
    WHERE L.LogID NOT IN (SELECT la.LogID 
                          FROM Logging.LogAttributes La
                          WHERE la.LogAttribute LIKE 'Bar%' )
    

    【讨论】:

    • 额外的括号在那里...删除它。
    【解决方案4】:
    SELECT *
    FROM Logging.Logs l Where l.LogId Not In ( Select la.LogId From Logging.LogAttributes la, Logging B Where 
    la.LogID = B.LogID AND la.LogAttribute NOT LIKE 'Bar%' )
    

    注意:NOT IN 查询对于大型数据集可能存在性能问题。

    更新:不存在可能比不存在更好。

    【讨论】:

    • 不存在更好吗?我正在处理一个大型数据集。
    • 是的,不存在更好。我应该提到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 2022-10-14
    • 1970-01-01
    • 2020-05-02
    相关资源
    最近更新 更多