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' 和子查询的主要内容,如果未能解决你的问题,请参考以下文章
prometheus使用postgresql-adapter连接postgresql
PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库
mac默认安装postgresql, 如何让postgresql可以远程访问