PostgreSQL 'NOT IN' 和子查询

Posted

技术标签:

【中文标题】PostgreSQL \'NOT IN\' 和子查询【英文标题】:PostgreSQL 'NOT IN' and subqueryPostgreSQL 'NOT IN' 和子查询 【发布时间】:2012-01-17 18:45:27 【问题描述】:

我正在尝试执行此查询:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (select consols.mac from consols)

但我没有得到任何结果。我测试了它,我知道语法有问题。在 mysql 中,这样的查询非常有效。我添加了一行以确保 mac 表中不存在一个 mac,但它仍然没有给出任何结果。

【问题讨论】:

consols.mac 列是NULL 还是NOT NULL 【参考方案1】:

当使用 NOT IN 时,您应该确保没有任何值是 NULL:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (
    SELECT mac
    FROM consols
    WHERE mac IS NOT NULL -- add this
)

【讨论】:

注意:不需要子查询中的WHERE mac IS NOT NULL 子句,因为In(...) 总是删除NULL(和重复项)。因为集合不能包含 NULL @wildplasser 我不知道。在我添加IS NOT NULL 之前,它对我不起作用。嵌套的SELECT 返回了几个NULLS,这让IN(SELECT...) 绊倒了。 我非常感谢您解释为什么 IS NOT NULL 会导致这个工作。 NOT IN 子句中使用NULL 似乎不起作用,因为与NULL 的比较既不是真也不是假。 sqlbadpractices.com/using-not-in-operator-with-null-values 如果子查询没有产生匹配的值和至少一个null 值,则查询将不返回没有is not null 的行。来自当前(版本 10)PostgreSQL 手册的section 9.22:“[...] 如果没有相等的右侧值并且至少右侧行产生 null,则 NOT IN 构造的结果将为 null,而不是真的。”【参考方案2】:

使用 NOT IN 时,您还应该考虑 NOT EXISTS,它会静默处理 null 情况。另见PostgreSQL Wiki

SELECT mac, creation_date 
FROM logs lo
WHERE logs_type_id=11
AND NOT EXISTS (
  SELECT *
  FROM consols nx
  WHERE nx.mac = lo.mac
  );

【讨论】:

还要注意使用NOT EXISTS... NOT IN 时的巨大性能损失 @IcanDivideBy0 在大多数情况下,它们生成相同的查询计划。你测试过吗? 在子查询的情况下,使用 NOT IN 代替 NOT EXISTS 还可以提高性能。见wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_NOT_IN【参考方案3】:

您也可以使用 LEFT JOIN 和 IS NULL 条件:

SELECT 
  mac, 
  creation_date 
FROM 
  logs
    LEFT JOIN consols ON logs.mac = consols.mac
WHERE 
  logs_type_id=11
AND
  consols.mac IS NULL;

“mac”列上的索引可能会提高性能。

【讨论】:

以上是关于PostgreSQL 'NOT IN' 和子查询的主要内容,如果未能解决你的问题,请参考以下文章

安装PostgreSQL和卸载PostgreSQL

prometheus使用postgresql-adapter连接postgresql

PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库

mac默认安装postgresql, 如何让postgresql可以远程访问

Wix,PostgreSQL 安装,执行 Postgresql 脚本

PostgreSQL学习总结—— PostgreSQL 语法