为什么 CROSS APPLY 列和聚合函数需要 Group by

Why CROSS APPLY with columns and aggregate functions needs Group by

问题

为什么在 SELECT 上混合使用列和聚合函数的 CROSS APPLY 查询不起作用?它需要 GROUP BY 子句或所有具有聚合函数的列。

代码

CREATE TABLE A
(
A_ID int identity(1,1), 
A_NAME Varchar(20)
)

INSERT INTO A (A_NAME)
VALUES
('A'), ('AA'), ('AAA')

CREATE TABLE B
(
B_ID int identity(10,10), 
B_NAME Varchar(20),
A_ID int
)

INSERT INTO B (B_NAME, A_ID)
VALUES
('B', 1), ('BB', 3), ('BBB', 2)

--如果 SELECT 的列与聚合函数

混合,则不起作用
    SELECT A_NAME, MAX(B_NAME)
    FROM A
    CROSS APPLY(SELECT * FROM B WHERE B.A_ID = A.A_ID) as AxB

--使用聚合函数

    SELECT MAX(A_NAME), MAX(B_NAME)
    FROM A
    CROSS APPLY(SELECT * FROM B WHERE B.A_ID = A.A_ID) as AxB

--与 GROUP BY

一起工作
    SELECT A_NAME, MAX(B_NAME)
    FROM A
    CROSS APPLY(SELECT * FROM B WHERE B.A_ID = A.A_ID) as AxB
    GROUP BY A_NAME

--重置

DROP TABLE A
DROP TABLE B

更新

结论(感谢@Richardissimo)

我有一个 Sybase 15.7 背景,在那里你可以混合使用聚合函数的列并且没有 Group by Clause。在那些情况下,默认组将是整个 table。所以在我的代码中,我期望 A Table 中所有 A_NAMES 的最大值 B_NAME。

然而,在 SQL 服务器中,当我在没有交叉应用的情况下测试代码时,我收到了同样的错误。看起来 SQL 服务器禁止这种行为。这有点酷,他们说 你在聚合查​​询中获得的行数不会超过组数

这就是一致性

此问题与 cross apply 无关,它与聚合的工作方式有关。让我们回顾一下您的 3 个场景:

SELECT A_NAME, MAX(B_NAME)Group By A_NAME 意味着您为每个不同的 A_NAME 返回一行,并且每个都将伴随 'biggest' 值 B_NAME 其中 A_NAME 具有该值。

SELECT MAX(A_NAME), MAX(B_NAME) 没有分组依据,这意味着对所有行进行分组,这意味着查询只会 return 一行。

SELECT A_NAME, MAX(B_NAME) 没有 Group By 没有意义。如果它只是 SELECT A_NAME,它会为每一行 return A_NAME 中的值。所以将 MAX(B_NAME) 放在同一个查询中是没有意义的,因为没有 Group By 它无法知道要聚合什么。

希望对您有所帮助。