MSSQL 无法理解“count(*) 小于 <some field of other table>”这个动作发生了什么

问题描述

我试图理解我正在做的练习的某些部分,但无法理解。

有一部分选择了“T”,按“a”分组,然后重定向到“具有计数(*)

我试过在谷歌上搜索这类东西,看看是否有类似的例子,但所有其他例子都使用常规数字,例如:“有计数(*)

练习是这样的:

MSSQL exercise

create table T(a int,b int);
insert into T values(1,2);
insert into T values(1,1);
insert into T values(2,3);
insert into T values(2,4);
insert into T values(3,4);
insert into T values(4,5);

select T3.b,(select count(T5.a) 
              from T T5 
              where T5.a = T3.b)
from (select T1.a as a,T2.b as b 
      from T T1,T T2 
      where T1.b < T2.a) as T3
where not exists (select T4.a 
                  from T T4
                  group by T4.a
                  having count(*) < T3.a);

我认为有 count(*) 是将分组的每个值与每行中 T3.a 的每个值进行比较,如果所有行都符合条件,则该值将被选中,但我以某种方式得到了不同的结果.

有人可以向我解释这个“具有计数(*)

提前致谢。

解决方法

从评论中重复我自己,对于聚合函数,HAVING 就像 WHERE。您不能在WHERE 中使用聚合函数,例如WHERE SUM(SomeColumn) > 5,因此您需要在HAVING 中使用它们:HAVING SUM(SomeColumn) > 5。这将返回组中列 SUMSomeColumn 大于 5 的任何行。

对于您的表达式,HAVING COUNT(*) < T3.a 只会返回 COUNT(*) 的值小于 T3.a 的值的行。

,

让我们把它分解成不同的部分。

首先是 FROM

from (select T1.a as a,T2.b as b 
      from T T1,T T2 
      where T1.b < T2.a) as T3

这使用旧式已弃用的交叉连接语法。可以重写为普通连接:

from (select T1.a as a,T2.b as b 
      from T T1
      join T T2 on T1.b < T2.a
) as T3

如果我们分析它的作用,我们就会意识到它实际上是所谓的三角连接:每一行都自连接到比它低的每一行。这通常在窗口聚合不可用时执行。


WHERE

where not exists (select T4.a 
                  from T T4
                  group by T4.a
                  having count(*) < T3.a);

这是一个相关子查询:T3.a 是对外部查询的引用。

这个谓词说的是:对于这个特定的行,子查询中必须没有行

子查询本身说:取 T 中的所有行,按 a 分组并计数,然后只包括计数小于外部引用 a 的行。

请注意,因为它是一个 EXIST,所以不使用实际选定的值。我怀疑这可能不是故意的。


SELECT

select T3.b,(select count(T5.a) 
              from T T5 
              where T5.a = T3.b)

然后我们从第一个连接中获取 b,并从所有匹配的 T 行的子查询中获取计数。同样,当窗口聚合不可用时,这很常见。


所以整个事情可以改写如下:

select T2.b,(select count(T5.a) 
              from T T5 
              where T5.a = T3.b)
from (
    select *,count(*) over (partition by a) as cnt
    from T
) T1
join T T2 on T1.b < T2.a
where T1.cnt < T1.a;

您查询中的逻辑有些不太正确,但不知道最初的意图是什么,也没有看到表和列名,我不能说。特别是三角形连接看起来很可疑。