Почему CROSS APPLY со столбцами и агрегатными функциями нуждается в Group by - PullRequest
0 голосов
/ 04 ноября 2018

ВОПРОС

Почему запрос CROSS APPLY со столбцами и агрегатными функциями, смешанными в SELECT, не работает? для этого требуется предложение 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

- РАБОТАЕТ С ГРУППА ПО

    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

UPDATE

ЗАКЛЮЧЕНИЕ (Спасибо @ Richardissimo's)

У меня есть фон Sybase 15.7, и там вы можете смешивать столбцы с агрегатными функциями, и у меня нет Group by Clause. в этих ситуациях группой по умолчанию будет вся таблица. поэтому в моем коде я ожидал Максимальное B_NAME для всех A_NAMES в таблице.

Однако в SQL Server, когда я тестировал код без перекрестного применения, я получил ту же ошибку. Похоже, что SQL Server запрещает этот тип поведения. Что довольно круто, при этом они говорят, что вы не получите больше строк, чем количество групп в агрегированном запросе.

ЭТО ПОСТОЯНИЕ

1 Ответ

0 голосов
/ 04 ноября 2018

Проблема не связана с 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 он не может знать, что агрегировать.

Надеюсь, это поможет.

...