如何在适逢周末或假期的日期加入最近的货币兑换日?
How to join most recent currency exchange date on a date which falls on a weekend or holiday?
我有一个 table 使用不同货币进行交易的交易,其中一些日期恰逢周末或假期。示例:
Date currency_code ammount
20-02-2017 EUR 55
18-02-2017 GBP 33
17-02-2017 EUR 44.55
我的 Currency
table 的示例:
SELECT rate,date, currency_code FROM exchangeTable:
rate Date currency_code
53,35 13-02-2017 ADP
53,35 14-02-2017 ADP
182,4 16-02-2017 ADP
192,45 17-02-2017 ADP
191,31 20-02-2017 ADP
是否可以在我的连接语句中使用一个简单的子查询,如果它是周末或假期,它将把最近的货币日期连接到我的交易日期?我想我应该在这里使用分区,但没有太多经验。
left join (?????????) a on a.date = b.date and a.currency_code= b.currency_code
您可以使用派生的 table、ROW_NUMBER
和分区来解决此问题。这样做的目的是使用 DATEPART
函数和 dw
(星期几)参数来消除周末,以忽略任何周六和周日。对于假期,您必须有 table 个假期日期,因为假期完全是主观的。
ROW_NUMBER
允许您在给定自定义排序和分区的情况下获取行号的索引。我们按货币划分,因此每次我们击中新货币时都会重置索引,我们按 DATE DESC
排序,因此每种货币的最近日期是 1
.
-- create a sample table with the date, currency, and exchange rate
create table rates (
id int identity(1,1) primary key,
date date not null,
currency char(3) not null,
rate decimal(10,2) not null
)
go
-- create table of holidays we'll use for excluding rates records later
create table holidays (
id int identity(1, 1) primary key,
date date not null,
name varchar(100) not null
)
-- create some sample data
-- Feb 18 and 19 are Saturday and Sunday
insert into rates (date, currency, rate) values
('2017-02-16', 'GBP', 1.23),
('2017-02-17', 'GBP', 1.24),
('2017-02-18', 'GBP', 1.25),
('2017-02-19', 'GBP', 1.26),
('2017-02-20', 'GBP', 1.27),
('2017-02-16', 'SGD', 2.23),
('2017-02-17', 'SGD', 2.24),
('2017-02-18', 'SGD', 2.25),
('2017-02-19', 'SGD', 2.26),
('2017-02-20', 'SGD', 2.27);
insert into holidays (date, name) values
('2017-02-20', 'National Cherry Pie Day'); -- this is a real thing
with t as (
select id,
date,
currency,
rate,
row_number() over (partition by currency order by date desc) as age
from rates
where datepart(dw, date) not in (1, 7) -- sunday, saturday
and date not in (select date from holidays) -- exclude holiday rates
)
select * from t where age = 1;
首先,您需要JOIN
Currency
table 的所有行具有相同的CurrencyCode
,然后您可以使用RANK() PARTITION (...
函数来select 与交易日期相比最近的日期。
SELECT
*
FROM
(SELECT
t.*,
c.*,
RANK() OVER (PARTITION BY t.ID ORDER BY ABS(DATEDIFF(d, t.[Date], c.[Date])) ASC, c.[Date] DESC) rn
FROM
Transactions t
INNER JOIN
Currency c ON t.CurrencyCode = c.CurrencyCode) t
WHERE
t.rn = 1
我有一个 table 使用不同货币进行交易的交易,其中一些日期恰逢周末或假期。示例:
Date currency_code ammount
20-02-2017 EUR 55
18-02-2017 GBP 33
17-02-2017 EUR 44.55
我的 Currency
table 的示例:
SELECT rate,date, currency_code FROM exchangeTable:
rate Date currency_code
53,35 13-02-2017 ADP
53,35 14-02-2017 ADP
182,4 16-02-2017 ADP
192,45 17-02-2017 ADP
191,31 20-02-2017 ADP
是否可以在我的连接语句中使用一个简单的子查询,如果它是周末或假期,它将把最近的货币日期连接到我的交易日期?我想我应该在这里使用分区,但没有太多经验。
left join (?????????) a on a.date = b.date and a.currency_code= b.currency_code
您可以使用派生的 table、ROW_NUMBER
和分区来解决此问题。这样做的目的是使用 DATEPART
函数和 dw
(星期几)参数来消除周末,以忽略任何周六和周日。对于假期,您必须有 table 个假期日期,因为假期完全是主观的。
ROW_NUMBER
允许您在给定自定义排序和分区的情况下获取行号的索引。我们按货币划分,因此每次我们击中新货币时都会重置索引,我们按 DATE DESC
排序,因此每种货币的最近日期是 1
.
-- create a sample table with the date, currency, and exchange rate
create table rates (
id int identity(1,1) primary key,
date date not null,
currency char(3) not null,
rate decimal(10,2) not null
)
go
-- create table of holidays we'll use for excluding rates records later
create table holidays (
id int identity(1, 1) primary key,
date date not null,
name varchar(100) not null
)
-- create some sample data
-- Feb 18 and 19 are Saturday and Sunday
insert into rates (date, currency, rate) values
('2017-02-16', 'GBP', 1.23),
('2017-02-17', 'GBP', 1.24),
('2017-02-18', 'GBP', 1.25),
('2017-02-19', 'GBP', 1.26),
('2017-02-20', 'GBP', 1.27),
('2017-02-16', 'SGD', 2.23),
('2017-02-17', 'SGD', 2.24),
('2017-02-18', 'SGD', 2.25),
('2017-02-19', 'SGD', 2.26),
('2017-02-20', 'SGD', 2.27);
insert into holidays (date, name) values
('2017-02-20', 'National Cherry Pie Day'); -- this is a real thing
with t as (
select id,
date,
currency,
rate,
row_number() over (partition by currency order by date desc) as age
from rates
where datepart(dw, date) not in (1, 7) -- sunday, saturday
and date not in (select date from holidays) -- exclude holiday rates
)
select * from t where age = 1;
首先,您需要JOIN
Currency
table 的所有行具有相同的CurrencyCode
,然后您可以使用RANK() PARTITION (...
函数来select 与交易日期相比最近的日期。
SELECT
*
FROM
(SELECT
t.*,
c.*,
RANK() OVER (PARTITION BY t.ID ORDER BY ABS(DATEDIFF(d, t.[Date], c.[Date])) ASC, c.[Date] DESC) rn
FROM
Transactions t
INNER JOIN
Currency c ON t.CurrencyCode = c.CurrencyCode) t
WHERE
t.rn = 1