SQL Server滞后/跨组领先/密集排名

时间:2018-08-24 04:52:57

标签: sql-server tsql window-functions sql-server-2017 lead

我希望找到有关如何填写超前和滞后值的答案。

输入:

BRAND   Promo_Start VALUE
TESLA   2016-06-05  NULL
TESLA   2016-06-12  NULL
TESLA   2016-06-19  40000
TESLA   2016-06-26  75000
TESLA   2016-07-03  75000
TESLA   2016-07-10  NULL

我想要的输出是:

BRAND   Promo_Start VALUE
TESLA   2016-06-05  40000
TESLA   2016-06-12  40000
TESLA   2016-06-19  40000
TESLA   2016-06-26  75000
TESLA   2016-07-03  75000
TESLA   2016-07-10  75000

我已经能够填写最后一个值,但是,我未能成功填写前两个值。

BRAND   Promo_Start VALUE   FILLED_VALUE
TESLA   2016-06-05  NULL    NULL
TESLA   2016-06-12  NULL    NULL
TESLA   2016-06-19  40000   40000
TESLA   2016-06-26  75000   75000
TESLA   2016-07-03  75000   75000
TESLA   2016-07-10  NULL    75000

使用此查询:

WITH help1 as (
SELECT *,
CASE WHEN [VALUE] IS NULL THEN 0 ELSE 1 END CHANGEINDICATOR
FROM #SOExample
)
, help2 as (
SELECT *, SUM(CHANGEINDICATOR) OVER (ORDER BY [Promo_Start]) RowGroup from help1
)
SELECT [BRAND],[Promo_Start],[VALUE],
CASE WHEN [VALUE] IS NOT NULL THEN [VALUE]
ELSE FIRST_VALUE([VALUE]) OVER (PARTITION BY RowGroup ORDER BY [Promo_Start])
END [FILLED_VALUE]
FROM help2
GO

表是使用以下方法创建的:

CREATE TABLE #SOExample
    ([BRAND] varchar(10),[Promo_Start] varchar(10), [VALUE] varchar(15))
;
GO

INSERT INTO #SOExample
    ([BRAND],[Promo_Start], [VALUE])
VALUES
    ('TESLA', '2016-06-05',NULL),
    ('TESLA', '2016-06-12',NULL),
    ('TESLA', '2016-06-19','40000'),
    ('TESLA', '2016-06-26','75000'),
    ('TESLA', '2016-07-03','75000'),
    ('TESLA', '2016-07-10',NULL)
;
GO

我认为这个问题可能类似于:LAG() / LEAD() of the next rank (Postgresql)  并且我已经看过this用于创建标志和this,因为它似乎是一个类似的问题。

我还研究了density_rank并使用了一个更改指示符(从NULL更改为下一行的值,并将值更改为下一行的NULL)。

2 个答案:

答案 0 :(得分:1)

0,第一个获取下一个非空值,第二个获取前一个非空值。

2 OUTER APPLY

答案 1 :(得分:1)

您只需要处理RowGroup = 0

时的情况
WITH help1 as (
SELECT *,
CASE WHEN [VALUE] IS NULL THEN 0 ELSE 1 END CHANGEINDICATOR
FROM #SOExample
)
, help2 as (
SELECT *, SUM(CHANGEINDICATOR) OVER (ORDER BY [Promo_Start]) RowGroup from help1
)
SELECT [BRAND],[Promo_Start],[VALUE],
CASE WHEN RowGroup = 0 THEN (Select [value] from help2 where RowGroup = 1)
ELSE FIRST_VALUE([VALUE]) OVER (PARTITION BY RowGroup ORDER BY [Promo_Start])
END [FILLED_VALUE]
FROM help2