从前一个日期检索最后一个有效值
Retrieve the last valid value from a previous date
我有以下 table“费率”:
aDate
realRate
isBusinessDay
01-04-22
1.10
1
02-04-22
1.20
1
03-04-22
1.30
1
04-04-22
1.40
0
05-04-22
1.50
0
06-04-22
1.60
1
07-04-22
1.70
1
08-04-22
1.80
1
09-04-22
1.90
1
10-04-22
2.00
0
11-04-22
2.10
0
12-04-22
2.20
0
13-04-22
2.30
0
14-04-22
2.40
1
15-04-22
2.50
1
16-04-22
2.60
1
17-04-22
2.70
1
18-04-22
2.80
0
19-04-22
2.90
0
20-04-22
3.00
0
21-04-22
3.10
1
我需要构建一个查询,该查询将 return 用于非工作日的前一个已知工作日的汇率。 “useThisRate”列是查询所需的结果:
aDate
realRate
isBusinessDay
useThisRate
01-04-22
1.10
1
1.10
02-04-22
1.20
1
1.20
03-04-22
1.30
1
1.30
04-04-22
1.40
0
1.30
05-04-22
1.50
0
1.30
06-04-22
1.60
1
1.60
07-04-22
1.70
1
1.70
08-04-22
1.80
1
1.80
09-04-22
1.90
1
1.90
10-04-22
2.00
0
1.90
11-04-22
2.10
0
1.90
12-04-22
2.20
0
1.90
13-04-22
2.30
0
1.90
14-04-22
2.40
1
2.40
15-04-22
2.50
1
2.50
16-04-22
2.60
1
2.60
17-04-22
2.70
1
2.70
18-04-22
2.80
0
2.70
19-04-22
2.90
0
2.70
20-04-22
3.00
0
2.70
21-04-22
3.10
1
3.10
请注意连续的非工作日天数未知。
任何帮助将不胜感激。
您可以执行一些 self-joins 和嵌入式子查询以使其工作。
我没有方便访问的 SQL 服务器,但查询如下所示。
SELECT aDate, realRate
FROM Rates
WHERE IsBusinessDay = 1
UNION ALL
SELECT sub.aDate, r3.realRate
FROM Rates r3
INNER JOIN (
SELECT r1.aDate,
(SELECT MAX(aDate)
FROM Rates r2
WHERE r2.aDate < r1.aDate
AND r2.isBusinessDay = 1) as LastDate
FROM Rates r1
WHERE r1.IsBusinessDay = 0
) sub
ON r3.aDate = sub.LastDate
基本上:
- 取所有工作日(第一次查询)
加上所有 non-business 天。对于那些:
- 对于每个 non-business 天,一个嵌入式子查询获取 MAX(),即小于 non-business 天的工作日。
- 然后加入实际 table 以获得该工作日的费率。
请注意,如果 table 中的行数非常大,这样的嵌入式查询可能会很昂贵,但由于您似乎每天有 1 行,所以您不应该有数百万行。原因是因为它使用 r1 table 作为过滤条件,服务器必须 re-execute r1 中每一行的子查询。
可能最直观的方式是关联查询。
您要么想要 realRate,要么 if non-business 天是工作日且日期早于当前行的最近的 realRate。
select *,
case when isBusinessDay = 1 then realrate
else (
select top(1) realrate
from rates r2
where r2.isBusinessDay = 1 and r2.aDate < r.adate
order by adate desc
)
end UseThisRate
from rates r;
您已经有了一个很好的答案,但只是提供另一种思考方式,即使用 APPLY
:
SELECT r.aDate, r.isBusinessDay, r.realRate,
UseThisRate = CASE r.isBusinessDay
WHEN 0 THEN x.prevRate ELSE r.realRate END
FROM dbo.Rates AS r
OUTER APPLY
(
SELECT TOP (1) prevRate = r2.realRate
FROM dbo.Rates AS r2
WHERE r2.isBusinessDay = 1
AND r2.aDate < r.aDate
ORDER BY r2.aDate DESC
) AS x;
我有以下 table“费率”:
aDate | realRate | isBusinessDay |
---|---|---|
01-04-22 | 1.10 | 1 |
02-04-22 | 1.20 | 1 |
03-04-22 | 1.30 | 1 |
04-04-22 | 1.40 | 0 |
05-04-22 | 1.50 | 0 |
06-04-22 | 1.60 | 1 |
07-04-22 | 1.70 | 1 |
08-04-22 | 1.80 | 1 |
09-04-22 | 1.90 | 1 |
10-04-22 | 2.00 | 0 |
11-04-22 | 2.10 | 0 |
12-04-22 | 2.20 | 0 |
13-04-22 | 2.30 | 0 |
14-04-22 | 2.40 | 1 |
15-04-22 | 2.50 | 1 |
16-04-22 | 2.60 | 1 |
17-04-22 | 2.70 | 1 |
18-04-22 | 2.80 | 0 |
19-04-22 | 2.90 | 0 |
20-04-22 | 3.00 | 0 |
21-04-22 | 3.10 | 1 |
我需要构建一个查询,该查询将 return 用于非工作日的前一个已知工作日的汇率。 “useThisRate”列是查询所需的结果:
aDate | realRate | isBusinessDay | useThisRate |
---|---|---|---|
01-04-22 | 1.10 | 1 | 1.10 |
02-04-22 | 1.20 | 1 | 1.20 |
03-04-22 | 1.30 | 1 | 1.30 |
04-04-22 | 1.40 | 0 | 1.30 |
05-04-22 | 1.50 | 0 | 1.30 |
06-04-22 | 1.60 | 1 | 1.60 |
07-04-22 | 1.70 | 1 | 1.70 |
08-04-22 | 1.80 | 1 | 1.80 |
09-04-22 | 1.90 | 1 | 1.90 |
10-04-22 | 2.00 | 0 | 1.90 |
11-04-22 | 2.10 | 0 | 1.90 |
12-04-22 | 2.20 | 0 | 1.90 |
13-04-22 | 2.30 | 0 | 1.90 |
14-04-22 | 2.40 | 1 | 2.40 |
15-04-22 | 2.50 | 1 | 2.50 |
16-04-22 | 2.60 | 1 | 2.60 |
17-04-22 | 2.70 | 1 | 2.70 |
18-04-22 | 2.80 | 0 | 2.70 |
19-04-22 | 2.90 | 0 | 2.70 |
20-04-22 | 3.00 | 0 | 2.70 |
21-04-22 | 3.10 | 1 | 3.10 |
请注意连续的非工作日天数未知。
任何帮助将不胜感激。
您可以执行一些 self-joins 和嵌入式子查询以使其工作。 我没有方便访问的 SQL 服务器,但查询如下所示。
SELECT aDate, realRate
FROM Rates
WHERE IsBusinessDay = 1
UNION ALL
SELECT sub.aDate, r3.realRate
FROM Rates r3
INNER JOIN (
SELECT r1.aDate,
(SELECT MAX(aDate)
FROM Rates r2
WHERE r2.aDate < r1.aDate
AND r2.isBusinessDay = 1) as LastDate
FROM Rates r1
WHERE r1.IsBusinessDay = 0
) sub
ON r3.aDate = sub.LastDate
基本上:
- 取所有工作日(第一次查询) 加上所有 non-business 天。对于那些:
- 对于每个 non-business 天,一个嵌入式子查询获取 MAX(),即小于 non-business 天的工作日。
- 然后加入实际 table 以获得该工作日的费率。
请注意,如果 table 中的行数非常大,这样的嵌入式查询可能会很昂贵,但由于您似乎每天有 1 行,所以您不应该有数百万行。原因是因为它使用 r1 table 作为过滤条件,服务器必须 re-execute r1 中每一行的子查询。
可能最直观的方式是关联查询。
您要么想要 realRate,要么 if non-business 天是工作日且日期早于当前行的最近的 realRate。
select *,
case when isBusinessDay = 1 then realrate
else (
select top(1) realrate
from rates r2
where r2.isBusinessDay = 1 and r2.aDate < r.adate
order by adate desc
)
end UseThisRate
from rates r;
您已经有了一个很好的答案,但只是提供另一种思考方式,即使用 APPLY
:
SELECT r.aDate, r.isBusinessDay, r.realRate,
UseThisRate = CASE r.isBusinessDay
WHEN 0 THEN x.prevRate ELSE r.realRate END
FROM dbo.Rates AS r
OUTER APPLY
(
SELECT TOP (1) prevRate = r2.realRate
FROM dbo.Rates AS r2
WHERE r2.isBusinessDay = 1
AND r2.aDate < r.aDate
ORDER BY r2.aDate DESC
) AS x;