MySQL - WHERE 子句中的 NOT IN 查询具有相同的结构,适用于第一个表但不适用于第二个表

Posted

技术标签:

【中文标题】MySQL - WHERE 子句中的 NOT IN 查询具有相同的结构,适用于第一个表但不适用于第二个表【英文标题】:MySQL - NOT IN query in WHERE clause with same structure working on first table but not on second table 【发布时间】:2013-09-06 16:33:50 【问题描述】:

我想将一个简单的 mysql 查询从一个表调整到另一个表。第一个查询按预期工作,但第二个修改后的查询未显示预期结果,但我无法弄清楚结构有什么不同。

这个问题与我之前认为已经解决的问题有关:

SQL IF ELSE / CASE clause in WHERE condition

简短地解释了查询应该做什么:

我想在 SQL SELECT 中编写一个 WHERE 条件,该条件应向我显示每个 ID 最多一个结果。但仅当 LANG 为 FR 或 EN 时,它才应显示结果。顶部应该首选 FR,并且仅当 ID 没有可用的 FR 时才应显示 EN 作为替代。所以结果应该是这样的。

这里是工作查询。这是 SQL Fiddle LINK

SELECT * FROM `table1`
WHERE ID = 4
AND lang = 'FR'
OR (lang = 'EN' AND ID = 4 NOT IN (SELECT ID FROM table1 WHERE lang = 'FR'))

这是结构相同的查询。这是 SQL Fiddle LINK

SELECT * FROM `epf_application_detail`
WHERE application_id = 281656475
AND language_code = 'PL'
OR (language_code = 'EN' AND application_id = 281656475 NOT IN (SELECT application_id FROM `epf_application_detail` WHERE language_code = 'PL'))

如果第二个小提琴可以正常工作,它应该会显示

+--------------+----------------+---------------+-----------+
|  export_date | application_id | language_code |    title  |
+--------------+----------------+---------------+-----------+
|1377594004198 | 281656475      | 'EN'          | 'PAC-MAN' |
+--------------+----------------+---------------+-----------+

我完全不知道有什么区别,所以非常感谢任何帮助

编辑:最适合我的解决方案(因为我需要将它与 union all 结合起来,并且每个 application_id 都需要一个结果)

SELECT *
FROM `epf_application_detail`
WHERE application_id = 281656475 AND
      (language_code = 'PL' OR
       (language_code = 'EN' AND
        application_id NOT IN (SELECT application_id
                               FROM `epf_application_detail`
                               WHERE language_code = 'PL' and application_id is not null
                              )
       )
      )

【问题讨论】:

AND application_id = 281656475 NOT IN 不等同于第一个查询。相当于AND true/false NOT IN 我在 SQL 方面不是很有经验,老实说,我并不真正理解“AND true/false NOT IN”是什么意思,也不知道如何纠正这个问题。我还更新了 ID = 4 的第一个查询,它也在更新的小提琴中工作 没有特定于 sql 的,如果是其他语言,它更像是if (($x == 281656475) && some_other_function) ... 【参考方案1】:

您的查询失败,因为您正在进行比较 not in:

SELECT *
FROM `epf_application_detail`
WHERE (application_id = 281656475 AND language_code = 'PL') OR
      (language_code = 'EN' AND
       application_id = 281656475 NOT IN (SELECT application_id
----------------------------------^
                                          FROM `epf_application_detail` WHERE language_code = 'PL'))

MySQL 将进行第一次比较,并将布尔结果转换为not in 的整数。根据第一个查询的结构,您希望:

SELECT *
FROM `epf_application_detail`
WHERE (application_id = 281656475 AND language_code = 'PL') OR
      (language_code = 'EN' AND
       application_id NOT IN (SELECT application_id
                              FROM `epf_application_detail`
                              WHERE language_code = 'PL' and application_id is not null
                             )
      )

我还添加了application_id is not null,因为NULL 会导致NOT IN 失败。

编辑:

根据您的评论,这应该符合您的逻辑:

SELECT *
FROM `epf_application_detail`
WHERE application_id = 281656475 AND
      (language_code = 'PL' OR
       (language_code = 'EN' AND
        application_id NOT IN (SELECT application_id
                               FROM `epf_application_detail`
                               WHERE language_code = 'PL' and application_id is not null
                              )
       )
      )

如果你只是从明细表中查找一行,下面的就简单多了:

SELECT *
FROM `epf_application_detail`
WHERE application_id = 281656475 AND
      language_code in ('PL', 'EN')
ORDER BY language_code = 'PL' desc
LIMIT 1;

这使用 MySQL 特定的语法。您的问题未标记 MySQL,但确实使用了 MySQL 语法。

【讨论】:

在原始表(相当大)上运行查询时,它给了我 868,013 个结果。它显示所有 application_id 的结果它不仅输出一个结果 application_id = 281656475 AND language_code = 'EN' 我认为我的请求可能没有明确提到这一点跨度> @VolkaRacho 。 . .如果你的条件是application_id = 281656475 AND language_code = 'EN',那你为什么有OR 子句呢?只需使用where 语句的第一部分。 我需要实现的是:如果 application_id = 281656475 AND language_code = 'PL' 存在则使用 application_id = 281656475 AND language_code = 'PL' 。但在某些情况下,ID 不存在 language_code = 'PL'(在这种情况下为:application_id = 281656475)。如果是这种情况,查询应输出此 application_id = 281656475 的值,但从始终存在的 language_code = 'EN' 所在的行输出。我对 SQL 的了解非常有限,这就是为什么我在链接的 *** 问题中询问解决方案的原因。在这里,其他人提出了 OR 的解决方案 太棒了!您的 EDIT 的第一个脚本完全符合我的需要,因为它还使用 union all 并为每个 application_id 显示一个结果。非常感谢!【参考方案2】:

你可以替换

 not IN

 and NOT exists


SELECT * FROM `epf_application_detail`
WHERE application_id = 281656475
AND language_code = 'PL'
OR (language_code = 'EN' AND
    application_id = 281656475 and NOT exists (SELECT application_id FROM `epf_application_detail` WHERE language_code = 'PL'))

【讨论】:

以上是关于MySQL - WHERE 子句中的 NOT IN 查询具有相同的结构,适用于第一个表但不适用于第二个表的主要内容,如果未能解决你的问题,请参考以下文章

MySQL UDF 仅适用于 `IF` 中的 `WHERE` 子句

WHERE子句MySQL中的PHP字符串变量

MySQL 的 WHERE 子句中的 CASE 或 COALESCE 性能

左连接的where子句中的Mysql查询错误

简单选择语句的where子句中的MySQL未知列

当列不明确时,有啥方法可以强制 Mysql 在 where 子句中使用 select 中的列?