【问题标题】:SQL: Select ID/Value combinations that do not possess a value in another tableSQL:选择在另一个表中不具有值的 ID/值组合
【发布时间】:2016-05-08 16:05:26
【问题描述】:

所以这基本上就是问题所在(我将把它变成一个更普遍的问题,以防人们将来需要这样的东西)。

我有一张桌子(“人”),基本上就是这样

╔══════════╦═══════╗
║ PersonID ║ Letter║
╠══════════╬═══════╣
║ 1        ║ A     ║
║ 1        ║ B     ║
║ 1        ║ C     ║
║ 1        ║ D     ║
║ 2        ║ A     ║
║ 2        ║ B     ║
║ 2        ║ C     ║
║ 3        ║ B     ║
║ 3        ║ C     ║
║ 4        ║ A     ║
║ 4        ║ C     ║
║ 4        ║ D     ║
║ 5        ║ E     ║
╚══════════╩═══════╝

假设我有另一个表(“字母”),它可以列出一个人可以拥有的所有可能的“字母”。

╔══════════╦══════╗
║ LetterID ║ Text ║
╠══════════╬══════╣
║ 1        ║ A    ║
║ 2        ║ B    ║
║ 3        ║ C    ║
║ 4        ║ D    ║
║ 5        ║ E    ║
╚══════════╩══════╝

我需要创建一个新表,其中列出所有人员以及他们没有的字母。所以对于这个例子,结果是这样的

╔══════════╦══════════════╗
║ PersonID ║ LetterNotHad ║
╠══════════╬══════════════╣
║ 1        ║ E            ║
║ 2        ║ D            ║
║ 2        ║ E            ║
║ 3        ║ A            ║
║ 3        ║ D            ║
║ 3        ║ E            ║
║ 4        ║ B            ║
║ 4        ║ E            ║
║ 5        ║ A            ║
║ 5        ║ B            ║
║ 5        ║ C            ║
║ 5        ║ D            ║
╚══════════╩══════════════╝

非常感谢任何和所有帮助或指导。

编辑:这基本上是我正在尝试的,类似这样的

select p.PersonId, l.value
from letters l
left join people p
on l.Text = p.Letter
where p.personid is null

【问题讨论】:

  • 您已将此标记为 MySQL 和 SQL-Server(-2008),它是什么?

标签: mysql sql sql-server database sql-server-2008


【解决方案1】:

因此,为了找到缺失值,您要做的是生成代表所有可能值的集合。这是两个集合(人和字母)之间的笛卡尔积,在 SQL 中,您使用 cross join 运算符(或非限定联接)来执行此操作。

您想从这个集合中删除已有的组合,其余的将是缺失的。

有很多方法可以做到这一点;使用左连接可能如下所示:

select sub.* 
from (
    select distinct personid, text 
    from people 
    cross join letters
) sub
left join people p on p.letter = sub.text and p.personid = sub.personid
where p.personid is null

或者使用except 集合运算符(对于MSSQL(Oracle 中的minus)- MySQL 没有这个):

select personid, text from people cross join letters
except 
select personid, letter from people

【讨论】:

    【解决方案2】:

    这就是想法

    WITH cte 
         AS (SELECT * 
             FROM   (SELECT DISTINCT personid 
                     FROM   people) B 
                    CROSS JOIN (SELECT DISTINCT Text as letter 
                                FROM   letters) A) 
    SELECT * 
    FROM   cte c 
    WHERE  NOT EXISTS (SELECT 1 
                       FROM   first_table f 
                       WHERE  c.personid = f.personid 
                              AND c.letter = f.letter) 
    

    注意:您需要在People 表中使用letterid 而不是Letter 并定义一个foreign key 以使表一致

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2016-12-28
      • 1970-01-01
      • 2021-07-17
      相关资源
      最近更新 更多