LAST_VALUE 函数未按预期工作

问题描述 投票:0回答:1

我使用的是 Microsoft SQL Azure (RTM) - 12.0.2000.8,我有一个表,其中包含提供商收到评级的多个日期。

我需要为每个提供商自 4 月 22 日以来的每个月输出一行,并包含该日期提供商的最新评级。

这是我必须使用的评级表:

日期 提供商 评分
2022-04-30 A 1
2022-05-31 B 2
2022-07-31 A 5

我尝试使用 LAST_VALUE 函数来完成此操作,但它并没有填充此内容。

WITH CTE_Dates AS ( --create date table as ratings table does not have record for every month

SELECT
EOMONTH([Date], 0) AS [ReportingDate]
FROM [tbl_Dates]
WHERE [Date] >= '2022-04-01'
AND [DATE] <= '2022-08-31'

GROUP BY EOMONTH([Date], 0)
)
,

CTE_Ratings AS (
SELECT
[ReportingDate]
,[Provider]
,[Rating]

FROM Ratings

)


SELECT
CTE_Dates.[ReportingDate]
,[Provider]
,[Rating]
,LAST_VALUE([Rating]) OVER (PARTITION BY CTE_Dates.[ReportingDate], [Provider] ORDER BY CTE_Dates.[ReportingDate]
        ) AS latest_rating

FROM CTE_Dates
LEFT OUTER JOIN CTE_Ratings
    ON CTE_Dates.[ReportingDate] = CTE_Ratings.[ReportingDate]

我的输出:

日期 提供商 评分 最新评级
2022-04-30 A 1 1
2022-05-31
2022-06-30
2022-07-31 A 5 5
2022-08-31
2022-04-30
2022-05-31 B 2 2
2022-06-30
2022-07-31
2022-08-31

所需输出:

日期 提供商 评分 最新评级
2022-04-30 A 1 1
2022-05-31 A 1
2022-06-30 A 1
2022-07-31 A 5 4
2022-08-31 A 5
2022-04-30 B
2022-05-31 B 2 2
2022-06-30 B 2
2022-07-31 B 2
2022-08-31 B 2
sql-server t-sql
1个回答
0
投票

如果我们使用您提供给我们的样本数据,您的查询和您所说的得到的结果肯定不一样。因此,我使用您的数据定义了一个

#Ratings
表并由自己的日历表使用。

首先,我得到每个月的最后一天,这可以通过

EOMONTH
实现,但我没有从日历表中得到每个日期;第一天就足够了,可以通过查询“日历日”列轻松返回。

然后,看来我们需要每个日期提供者一个不同的行,这是您的查询所缺少的。这可以通过日期 CTE 和

CROSS JOIN
表之间的
Ratings
来完成,并获取两列组合的
DISTINCT
值。然而,理想情况下,您会
CROSS JOIN
Provider
表,以消除
DISTINCT

尽管样本数据表明并非如此,但我假设

Rating
的值 总是增加。如果是,那么窗口
MAX
就可以工作。然而,假设不是,那么您在这里缺少的是
IGNORE NULLS
运算符。如果添加它,您将获得所需的结果,因为获取
最后一个值
时会忽略 NULLs 值。

CREATE TABLE #Ratings (Date date,
                       Provider char(1),
                       Rating int);
GO

INSERT INTO #Ratings (Date,
                      Provider,
                      Rating)
VALUES('2022-04-30','A',1),
      ('2022-05-31','B',2),
      ('2022-07-31','A',5);
GO

WITH Dates AS(
    SELECT EOMONTH(CalendarDate) AS [ReportingDate]
    FROM tbl.Calendar
    WHERE CalendarDate >= '2022-04-01'
         AND CalendarDate <= '2022-08-31'
         AND CalendarDay = 1),
RatingDates AS(
    SELECT DISTINCT 
           R.Provider,
           D.ReportingDate
    FROM #Ratings R
         CROSS JOIN Dates D)
SELECT RD.[ReportingDate],
       RD.[Provider],
       LAST_VALUE(R.Rating) IGNORE NULLS OVER (PARTITION BY RD.Provider ORDER BY RD.ReportingDate) AS Rating
FROM RatingDates RD
     LEFT OUTER JOIN #Ratings R ON RD.[ReportingDate] = R.Date
                               AND RD.Provider = R.Provider
ORDER BY RD.Provider,
         RD.ReportingDate;
GO

DROP TABLE #Ratings
© www.soinside.com 2019 - 2024. All rights reserved.