不要意外地没有产生任何行

时间:2016-04-06 14:59:14

标签: mysql mariadb having mysql-5.5 notin

我有一个用户定义的函数udf,在MariaDB 5.5中返回一个布尔值。

以下内容给出了我的期望:

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(如上表所示),正如我所期望的那样:

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;

然而,它没有给我任何行。为什么呢?

1 个答案:

答案 0 :(得分:2)

如注释中所述,如果子查询返回的任何行都是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(*)。也就是说,它不是获取具有相同字段的所有行,而是在获得第二个字段时停止:

where not exists (select 1 
                  from tbl t2
                  where tbl.fld = t2.fld and
                        tbl.id <> t2.id -- or some appropriate column
                 )