7

我有一个查询需要返回子查询中不匹配的结果。子查询可以返回一个空结果,所以如果子查询返回一个空集,我需要设置一个默认值(比如 0),以防止IN (NULL)它总是返回另一个 NULL。

例如

SELECT * FROM example_table WHERE id NOT IN (subquery_that_selects_ids)

subquery_that_selects_ids如果子查询没有找到匹配的结果,则可以返回一组整数,即 (1,2,5,6) 或空集。

COALESCE在这里不起作用,因为子查询可能会返回多个结果。

解决方案需要在 SQLite 或 postgresql 中运行。如何防止子查询返回空集?


每个人都告诉我查询应该按书面方式工作。你们都是对的。该查询是由 Rails3 的 AREL 构建的,当我准备在这里发布完整的查询时,我注意到 AREL 在使用数组条件时将 NULL 放入空集。

IE 我在 rails 中的查询看起来像:

Object.where("id NOT IN (?)", Object.where(other_conditions).select(:id))

Object.where(other_conditions)评估为[]?替换为NULL

所以我重新编写查询看起来像:

Object.where("id NOT IN (" + Object.where(other_conditions).select(:id).to_sql + ")")

问题解决了。

我赞扬@Michael Buen,但也赞成任何告诉我查询会按书面形式工作的人,因为它们是正确的。特别感谢@OMG Ponies 和@Ted Elliott!

4

5 回答 5

5

尝试:

SELECT * FROM example_table 
WHERE id NOT 
    IN (select x.id from subquery_that_selects_ids as x where x.id is not null)

我认为你有点复杂,即使子查询中没有行,NOT IN 也会有行。您的查询无需修改即可工作。无论如何,如果您真的希望您的子查询即使条件不满足也能产生行,请使用 UNION

SELECT * FROM example_table 
WHERE id NOT 
    IN (select x.id from subquery_that_selects_ids as x 
        where 1 = 0 -- empty set
        union
        select 0)

UNION 无论如何都会消除重复,UNION ALL 保留重复

于 2010-12-20T03:38:46.167 回答
2

关于什么:

SELECT ex.ID, ex.OtherFields
FROM ExampleTable ex left join (Select ID from SomeOtherTable) o on o.ID = ex.ID
WHERE o.ID is null
于 2010-12-20T03:33:15.147 回答
2

我认为你混淆了一些东西。如果subquery_that_selects_ids返回一个空集(因此选择了每一行example_table),您发布的查询就可以正常工作。这里不涉及隐式空值。

您可能正在考虑将子查询用作标量的情况。在这种情况下,如果子查询不返回任何行,则结果值为 null,例如,

SELECT * FROM example_table WHERE id = (SELECT id FROM other_table WHERE name = 'foo')
于 2010-12-20T22:20:09.603 回答
0

为什么这行不通?

SELECT *
  FROM example_table
 WHERE id IN (
    SELECT COALESCE(id, 0)
      FROM another_example_table
);
于 2010-12-20T03:09:56.520 回答
0

如果您使用 NOT in 运算符并且如果子查询返回的集合包含 NULL 值,则在多值子查询中会出现问题。如果子查询是一个空集,那并不意味着它返回 null ;)

在包含空值的情况下,它会强制外部查询返回一个空集,因为它无法判断该值是在 UNKNOWN 还是 NOT IN Unknown。

这是一个使用hr.employees 表的示例。

*从hr.employees中选择last_name,其中commission_pct NOT IN (0.1,0.35);*

此查询将返回 26 行。

*从hr.employees中选择last_name,其中commission_pct NOT IN (0.1,0.35,NULL);*

此查询不返回任何行,因为传递给 NOT IN 的列表中的 NULL 会破坏它。所以,如果您的子查询可能返回任何空值,您应该使用子查询中的函数 (NVL,NVL2,COALESCE) 来处理它。

希望这有帮助。

谢谢

亚历山大·布法罗

于 2014-03-07T00:57:21.107 回答