Когда я использую FIRST_VALUE в наборе данных, который я создаю вручную, я получаю один результат, и когда я использую его в наборе данных, который получается из левого соединения, у меня получается другой результат - даже если наборы данных выглядят я должен содержать точные значения данных. Я воспроизвел проблему с помощью простого набора данных ниже.
Может ли кто-нибудь сказать мне, если я что-то не понял?
Этот SQL производит ожидаемый результат, что FIRST_VALUE имеет значение NULL и LAST_VALUE равно 30.
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
(
SELECT 1 agroup, 10 aval
UNION ALL SELECT 1, NULL
UNION ALL SELECT 1, 30
) T
Этот SQL использует LEFT JOIN, который приводит к тому же набору данных, что и выше, но FIRST_VALUE, как представляется, игнорирует NULL.
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
(
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
) T
Я также могу показать, что поведение левого соединения отличается при использовании переменной таблицы против CTE. При использовании CTE для генерации данных FIRST_VALUE игнорирует NULL. Использование одного и того же SQL, но включение результатов в переменную таблицы или временную таблицу приводит к принятию значения NULL.
При CTE результаты SQL Server не включают NULL в определение FIRST_VALUE:
WITH T AS
(
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
)
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
T
Но с переменной таблицы она:
DECLARE @T TABLE (agroup INT,akey INT,aval INT)
INSERT INTO
@T
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
@T