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 我认为具有 count(*) 是在将分组的每个值与每行中 T3.a 的每个值进行比较,如果所有行都符合标准,则该值被选中,但不知何故我得到了不同的结果. 有人可以向我解释一下这个“拥有 count(*)
提前谢谢你。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);
【问题讨论】:
HAVING
类似于WHERE
,但用于聚合函数。您不能使用WHERE SUM(YourColumn) > 5
,但可以在HAVING
中使用SUM
表达式。你读过documentation吗?
@Larnu 首先感谢您的回复,我已阅读文档,但我不明白将整列表与有语句中的单个值进行比较时发生了什么。
这是我不明白的部分:“有 count(*)
有什么不明白的,恕我直言,不难表达;其中(组中)的行数小于T3.a
的值。您不清楚其中的哪一部分?
假设 T3 有 3 行,所以当我执行“具有 count(*)
【参考方案1】:
在 cmets 中重复一遍,HAVING
就像聚合函数的 WHERE
。 WHERE
中不能使用聚合函数,例如WHERE SUM(SomeColumn) > 5
,所以需要在HAVING
:HAVING SUM(SomeColumn) > 5
中使用。这将返回组中SomeColumn
列的SUM
大于5 的任何行。
对于您的表达式,HAVING COUNT(*) < 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 无法理解“计数(*)小于 <其他表的某个字段>”的操作发生了啥的主要内容,如果未能解决你的问题,请参考以下文章
使用 ActiveDirectoryMSI、MSSQL 和 SQLServerDataSource 时无法配置数据源:“url”