2010-01-26 100 views
16

通常我只是在代碼本身做這件事,但我很好奇這是否可以在TSQL中有效地完成。SQL加入最近的日期

Table 1 
Date - Value 
Table 2 
Date - Discount 

表1包含的每一天的條目。表2僅包含折扣更改時的條目。應用於某個值的折扣在輸入新折扣之前被視爲有效。

示例數據:

Table 1 
1/26/2010 - 10 
1/25/2010 - 9 
1/24/2010 - 8 
1/24/2010 - 9 
1/23/2010 - 7  
1/22/2010 - 10 
1/21/2010 - 11 
 
Table 2 
1/26/2010 - 2 
1/23/2010 - 1 
1/20/2010 - 0 

我需要返回如下:T1 Date - T1 Value - T2 Discount

示例數據:

 
1/26/2010 - 10 - 2  
1/25/2010 - 9 - 1 
1/24/2010 - 8 - 1 
1/24/2010 - 9 - 1 
1/23/2010 - 7 - 1  
1/22/2010 - 10 - 0 
1/21/2010 - 11 - 0 

可能還是我最好還是先繼續做這在代碼中?

回答

18

我相信這個子查詢會做到這一點(未測試)。

select *, 
    (select top 1 Discount 
    from table2 
    where table2.Date <= t.Date 
    order by table2.Date desc) as Discount 
from Table1 t 

但也許不是最高性能的。

編輯:

測試代碼:

create table #table1 ([date] datetime, val int) 
create table #table2 ([date] datetime, discount int) 

insert into #table1 ([date], val) values ('1/26/2010', 10) 
insert into #table1 ([date], val) values ('1/25/2010', 9) 
insert into #table1 ([date], val) values ('1/24/2010', 8) 
insert into #table1 ([date], val) values ('1/24/2010', 9) 
insert into #table1 ([date], val) values ('1/23/2010', 7) 
insert into #table1 ([date], val) values ('1/22/2010', 10) 
insert into #table1 ([date], val) values ('1/21/2010', 11) 

insert into #table2 ([date], discount) values ('1/26/2010', 2) 
insert into #table2 ([date], discount) values ('1/23/2010', 1) 
insert into #table2 ([date], discount) values ('1/20/2010', 0) 

select *, 
    (select top 1 discount 
    from #table2 
    where #table2.[date] <= t.[date] 
    order by #table2.[date] desc) as discount 
from #table1 t 

drop table #table1 
drop table #table2 

結果:

 
2010-01-26 00:00:00.000 10 2 
2010-01-25 00:00:00.000 9 1 
2010-01-24 00:00:00.000 8 1 
2010-01-24 00:00:00.000 9 1 
2010-01-23 00:00:00.000 7 1 
2010-01-22 00:00:00.000 10 0 
2010-01-21 00:00:00.000 11 0 
12

無 「最近」 的查詢會作爲 「等於」 查詢被視爲有效,但這是可靠的另一項工作ROW_NUMBER

;WITH Discounts_CTE AS 
(
    SELECT 
     t1.[Date], t1.[Value], t2.Discount, 
     ROW_NUMBER() OVER 
     (
      PARTITION BY t1.[Date] 
      ORDER BY t2.[Date] DESC 
     ) AS RowNum 
    FROM Table1 t1 
    INNER JOIN Table2 t2 
     ON t2.[Date] <= t1.[Date] 
) 
SELECT * 
FROM Discounts_CTE 
WHERE RowNum = 1 
+0

+1:好主意。看到子查詢的基準標記與連接row_number會很有趣。 – Joel 2010-01-26 22:27:37

0

這適用於Oracle XE。由於sql server確實具有分析功能,所以不應該難以移植它。

create table one (
    day date, 
    value integer 
); 


create table two (
    day date, 
    discount integer 
); 


insert into one values (trunc(sysdate), 10); 
insert into one values (trunc(sysdate-1), 8); 
insert into one values (trunc(sysdate-2), 1); 
insert into one values (trunc(sysdate-3), 23); 
insert into one values (trunc(sysdate-4), 3); 
insert into one values (trunc(sysdate-5), 4); 
insert into one values (trunc(sysdate-6), 8); 
insert into one values (trunc(sysdate-7), 5); 
insert into one values (trunc(sysdate-8),8); 
insert into one values (trunc(sysdate-9), 8); 
insert into one values (trunc(sysdate-10), 5);  


insert into two values (trunc(sysdate), 2); 
insert into two values (trunc(sysdate-3), 1); 
insert into two values (trunc(sysdate-5), 3); 
insert into two values (trunc(sysdate-8), 1); 


select day, value, discount, cnt, 
    nvl(max(discount) over (partition by cnt) 
    ,0) as calc_discount 
from (
    select day, value, discount, 
     count(discount) over (order by day) as cnt 
    from one 
    left outer join two 
    using(day) 
)