NOT IN 出乎意料地没有产生任何行
NOT IN yielding no rows, unexpectedly
我在 MariaDB 5.5 中有一个用户定义的函数 udf
returns 一个布尔值。
以下给出了我的期望:
select c, count(*)
from (
select fld, count(*)c
from tbl
where udf(fld)
group by fld
) t
group by c;
+---+----------+
| c | count(*) |
+---+----------+
| 1 | 12345 |
| 2 | 1234 |
| 3 | 123 |
| 4 | 12 |
| 5 | 1 |
+---+----------+
5 rows in set (26.75 sec)
同样,下面给出了数字 12345
(来自上面的 table),正如我所期望的:
select anotherfield, count(*)
from tbl
where udf(fld)
and fld in (
select fld from (
select fld,count(*)c
from tbl
group by fld
having c=1
)t
)
group by anotherfield with rollup;
我希望以下内容也会给我 12345
:
select anotherfield, count(*)
from tbl
where udf(fld)
and fld not in (
select fld from (
select fld,count(*)c
from tbl
group by fld
having c>1
)t
)
group by anotherfield with rollup;
但是,它没有给我任何行。为什么?
如评论中所述,如果子查询返回的任何行是 NULL
,则您不会返回任何行。一种解决方案是明确过滤它们:
where fld not in (select fld
from tbl
where fld is not null
group by fld
having count(*) > 1
)
我的首选方法是使用 not exists
,因为它具有正确的语义:
where not exists (select 1
from tbl t2
group by fld
having count(*) > 1 and
tbl.fld = t2.fld
)
也就是说,更有效的方法通常是在行中找到一些差异,而不是检查 count(*)
。也就是说,不是获取 all 具有相同字段的行,它可以在获取第二个时停止:
where not exists (select 1
from tbl t2
where tbl.fld = t2.fld and
tbl.id <> t2.id -- or some appropriate column
)
我在 MariaDB 5.5 中有一个用户定义的函数 udf
returns 一个布尔值。
以下给出了我的期望:
select c, count(*)
from (
select fld, count(*)c
from tbl
where udf(fld)
group by fld
) t
group by c;
+---+----------+
| c | count(*) |
+---+----------+
| 1 | 12345 |
| 2 | 1234 |
| 3 | 123 |
| 4 | 12 |
| 5 | 1 |
+---+----------+
5 rows in set (26.75 sec)
同样,下面给出了数字 12345
(来自上面的 table),正如我所期望的:
select anotherfield, count(*)
from tbl
where udf(fld)
and fld in (
select fld from (
select fld,count(*)c
from tbl
group by fld
having c=1
)t
)
group by anotherfield with rollup;
我希望以下内容也会给我 12345
:
select anotherfield, count(*)
from tbl
where udf(fld)
and fld not in (
select fld from (
select fld,count(*)c
from tbl
group by fld
having c>1
)t
)
group by anotherfield with rollup;
但是,它没有给我任何行。为什么?
如评论中所述,如果子查询返回的任何行是 NULL
,则您不会返回任何行。一种解决方案是明确过滤它们:
where fld not in (select fld
from tbl
where fld is not null
group by fld
having count(*) > 1
)
我的首选方法是使用 not exists
,因为它具有正确的语义:
where not exists (select 1
from tbl t2
group by fld
having count(*) > 1 and
tbl.fld = t2.fld
)
也就是说,更有效的方法通常是在行中找到一些差异,而不是检查 count(*)
。也就是说,不是获取 all 具有相同字段的行,它可以在获取第二个时停止:
where not exists (select 1
from tbl t2
where tbl.fld = t2.fld and
tbl.id <> t2.id -- or some appropriate column
)