MSSQL 无法理解“计数(*)小于 <其他表的某个字段>”的操作发生了啥

Posted

技术标签:

【中文标题】MSSQL 无法理解“计数(*)小于 <其他表的某个字段>”的操作发生了啥【英文标题】:MSSQL can't understand what's happening with the action "having count(*) lesser than <some field of other table>"MSSQL 无法理解“计数(*)小于 <其他表的某个字段>”的操作发生了什么 【发布时间】:2021-06-04 03:45:46 【问题描述】:

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

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

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

练习是这样的:

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 的每个值进行比较,如果所有行都符合标准,则该值被选中,但不知何故我得到了不同的结果.

有人可以向我解释一下这个“拥有 count(*)

提前谢谢你。

【问题讨论】:

HAVING 类似于WHERE,但用于聚合函数。您不能使用WHERE SUM(YourColumn) &gt; 5,但可以在HAVING 中使用SUM 表达式。你读过documentation吗? @Larnu 首先感谢您的回复,我已阅读文档,但我不明白将整列表与有语句中的单个值进行比较时发生了什么。 这是我不明白的部分:“有 count(*) 有什么不明白的,恕我直言,不难表达;其中(组中)的行数小于T3.a 的值。您不清楚其中的哪一部分? 假设 T3 有 3 行,所以当我执行“具有 count(*) 【参考方案1】:

在 cmets 中重复一遍,HAVING 就像聚合函数的 WHEREWHERE中不能使用聚合函数,例如WHERE SUM(SomeColumn) &gt; 5,所以需要在HAVING:HAVING SUM(SomeColumn) &gt; 5中使用。这将返回组中SomeColumn 列的SUM 大于5 的任何行。

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

【讨论】:

【参考方案2】:

让我们将其分解为单独的部分。

首先是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;

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

【讨论】:

以上是关于MSSQL 无法理解“计数(*)小于 <其他表的某个字段>”的操作发生了啥的主要内容,如果未能解决你的问题,请参考以下文章

无法连接到 docker 托管的 MSSQL

无法正确查询(MSSQL - PHP - JSON)

SQLAlchemy 无法连接到 mssql 数据库

PHP 中的 MSSQL 日期时间无法正常工作

使用 ActiveDirectoryMSI、MSSQL 和 SQLServerDataSource 时无法配置数据源:“url”

node mssql 无法连接sql server