【问题标题】:Access: WHERE IN AND NOT IN on same column访问:WHERE IN AND NOT IN 在同一列
【发布时间】:2022-01-20 07:13:38
【问题描述】:

假设我有一张 animal 桌和一张 competition 桌,其关系为 1:n。

表格动物看起来像:

id_animal type
1 cat
2 dog

比赛看起来像:

id_competition fid_animal name
1 1 A
2 2 A
3 2 B

这意味着猫参加比赛 A,狗参加比赛 A 和 B。

我现在想根据表 competition 中的条目过滤表 animal

查询听起来像:

向我展示所有参加比赛(名称)A 而不是 B 的动物(类型)。结果应该只给我猫,而不是狗。

我用下面的 sql(简化)试试运气:

Select DISTINCT * FROM animal 
LEFT JOIN competition ON id_animal = fid_animal 
WHERE competition.name IN ("A") AND NOT competition.name IN ("B");

结果我得到了猫和狗。 只有 AND NOT 把狗还给我,这很好,但两者一起都没有给我想要的结果。

我做错了什么?如何实现输出?

提前谢谢你!

背景: 我有一个包含大量条目的绑定表单(数据表)和一个表作为数据源。用户应该能够根据相关 (1:n) 表中的参数过滤表单。所以我用列表框(填充了相关表的可能条目)制作了一个未绑定的表单,用户可以在其中选择多个条件。结果是一个类似上面的 sql 语句,用作绑定表单的新数据源。这个逻辑运行良好。问题是有时表单中的条目可以有多个参数,对于用户来说,按所选参数过滤很重要,但如果结果包含特定的其他参数,则排除结果。有一些相关的表,许多列表框是过滤器的一部分,并且 sql 字符串是根据用户选择的 if 和内容动态生成的。

【问题讨论】:

标签: sql ms-access


【解决方案1】:

MS Access 通常远不符合标准。以下是标准 SQL 中的简单查询,几乎在每个 RDBMS 中运行:

SELECT *
FROM animal 
WHERE id_animal IN (SELECT id_animal FROM competition WHERE name = 'A')
  AND id_animal NOT IN (SELECT id_animal FROM competition WHERE name = 'B');

[NOT] IN 适用于列表。在单项列表上使用它没有什么意义。 name IN ("A")name = "A" 相同。由于要在比赛表中查找动物列表,因此需要如上所示的子查询。

如你所见,我不加入。我为什么要?我想选择动物,所以我从动物表中选择。我想将结果限制在某些动物身上,所以我使用了WHERE 子句。

我注意到您对字符串文字使用了双引号。如果这在 MS Access 中是必需的,则将上面的单引号替换为双引号。 (在标准 SQL 双引号中分隔名称,而不是字符串文字,但这在 MS Access 中可能有所不同。)

【讨论】:

  • Access 接受引号或撇号来分隔字符串文字。对象名称以[ ] 分隔,并且仅当名称包含空格或标点符号或以数字开头或为保留字时才需要。
【解决方案2】:

考虑:

SELECT animal.* FROM animal LEFT JOIN competition ON id_animal = fid_animal 
WHERE [name]="A" AND NOT id_animal IN (SELECT fid_animal FROM competition WHERE [name]="B")

可能会发现这个相关的感兴趣的问题Microsoft Access - Filtering a form based on check boxes for one field

【讨论】:

    【解决方案3】:

    您需要查看几行。你的谓词:

    WHERE competition.name IN ("A") AND NOT competition.name IN ("B");
    

    针对同一行进行评估。它将查找名称为“A”而不是“B”的所有行,即比赛 1 和 2。如果您改为查看名称为“A”的行,其中不存在名称为“B”的同一动物的行' 你会找到你要找的东西:

    SELECT c1.fid_animal
    FROM competition c1
    WHERE c1.name = 'A'
      AND NOT EXISTS (
          SELECT * 
          FROM competition c2
          WHERE c1.fid_animal = c2.fid_animal
            AND c2.name = 'B'
    ) 
    

    现在您可以将此结果与动物相结合以查找类型:

    SELECT a.type
    FROM competition c1
    
    JOIN animal a
        ON a.id_animal = c1.fid_animal
    
    WHERE c1.name = 'A'
      AND NOT EXISTS (
          SELECT * 
          FROM competition c2
          WHERE c1.fid_animal = c2.fid_animal
            AND c2.name = 'B'
    );
    

    FWIW,type 是 SQL 中的保留字,因此您应避免将其用作标识符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      相关资源
      最近更新 更多