为什么对列和聚合函数进行交叉应用需要分组依据

时间:2018-11-04 19:41:05

标签: sql sql-server cross-apply

问题

为什么在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 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's

我具有Sybase 15.7的背景,您可以在其中混合具有聚合功能的列,并且没有“分组依据”子句。在这种情况下,默认组将是整个表。因此在我的代码中,我期望A表中所有A_NAMES的最大B_NAME。

但是,在SQL Server中,当我测试没有交叉应用的代码时,我收到了相同的错误。看起来SQL Server禁止这种行为。这样做很酷,他们说在汇总查询中,您获得的行数不会超过组数

这就是一致性

1 个答案:

答案 0 :(得分:3)

该问题与cross apply无关,它与聚合的工作方式有关。让我们回顾一下您的3种情况:

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

SELECT MAX(A_NAME), MAX(B_NAME)没有分组依据,这意味着将对所有行进行分组,这意味着查询将仅返回单个行。

没有SELECT A_NAME, MAX(B_NAME)

Group By没有任何意义。如果只是SELECT A_NAME,它将为每一行返回A_NAME中的值。因此,将MAX(B_NAME)放在同一个查询中是没有意义的,因为如果没有Group By,它就无法知道要汇总的内容。

希望这会有所帮助。