我有一个带日历的桌子和一个带利率的桌子。在包含费率的表中,周末中没有几天的值存在。我正在尝试将两者合并,以便获得一个表格,列出所有天的费率,我需要将周末的费率作为最新的费率。它的Instad显示NULL值,就像您进行左连接并且该记录不存在时一样,它应该只取最新的可用值,并重复先前的值。
我有下面的代码,可以正常工作,但是在7,397行上需要2分钟,这太长了。
有人知道更快的方法来获得相同的结果吗?
SELECT
c.CalendarID,
MAX(r.RateID)
FROM Dim_Calendar c
LEFT JOIN Dim_Rates r ON r.RateDate <= c.CalendarID
在没有<=而只有=的情况下,我得到的是以下内容
CalendarID | RateID
20131001 | 2
20131002 | 3
20131003 | 4
20131004 | 5
20131005 | NULL
20131006 | NULL
20131007 | 6
这是所需的表:
CalendarID | RateID
20131001 | 2
20131002 | 3
20131003 | 4
20131004 | 5
20131005 | 5
20131006 | 5
20131007 | 6
答案 0 :(得分:1)
您可以使用相关的子查询来填补空白:
SELECT
c.CalendarID,
(SELECT TOP 1 r.RateID FROM Dim_Rates r
WHERE r.RateDate <= c.CalendarID AND r.RateID IS NOT NULL
ORDER BY r.RateDate DESC) AS RateID
FROM Dim_Calendar c
ORDER BY c.CalendarID;
可以使用以下索引改进此查询:
CREATE INDEX idx ON Dim_Rates (RateDate, RateID);
答案 1 :(得分:1)
您可以使用LAG()
窗口功能:
SELECT c.CalendarID,
COALESCE(
r.RateID,
LAG(r.RateID, 1) OVER (ORDER BY c.CalendarID),
LAG(r.RateID, 2) OVER (ORDER BY c.CalendarID)
) RateID
FROM Dim_Calendar c LEFT JOIN Dim_Rates r
ON r.RateDate = c.CalendarID
ORDER BY c.CalendarID
请参见demo。
结果:
> CalendarID | RateID
> ---------: | :-----
> 20131001 | 2
> 20131002 | 3
> 20131003 | 4
> 20131004 | 5
> 20131005 | 5
> 20131006 | 5
> 20131007 | 6
答案 2 :(得分:0)
如前所述,您需要检查索引是否正确和覆盖范围。看来您正在针对DW DB运行a,如果是这种情况,那么如果查询计划中估计的行数估算值不理想,则可以用索引临时表替换CTE。
;WITH NormalizedData AS
(
SELECT
RateID,CalendarID,
VirtualGroupID = SUM(LastRecordBeforeGap) OVER (ORDER BY CalendarID ROWS UNBOUNDED PRECEDING)
FROM
(
SELECT RateID,CalendarID,
LastRecordBeforeGap = CASE WHEN LEAD(RateID) OVER(ORDER BY CalendarID) IS NULL AND RateID IS NOT NULL THEN 1 ELSE 0 END
FROM
Dim_Calendar c
LEFT JOIN Dim_Rates r ON r.RateDate = c.CalendarID
)AS x
)
SELECT
RateID = ISNULL(RateID, SUM(RateID) OVER(PARTITION BY VirtualGroupID)),
CalendarID
FROM
NormalizedData