2014-10-30 70 views
0

我有我想象的是一個有點基本的SQL問題,並希望得到一些幫助。我正在使用MSSQL。有條件的SQL加入

我有兩個表:

 
Table A       Table B 
---------------------------------------------- 
A.ID |A.Date|     B.ID|B.Date|B.Number 

A.ID是獨一無二的;沒有重複的行。 B.ID不唯一,因此連接該列上的表可能導致返回多行。爲了獲得正確的記錄,必須加入兩欄,但這也有不良結果的問題。例如:

 
Table A    |   Table B 
---------------------------------------------- 
1  |01-01-2014  |  1 |01-01-2014|25 
2  |01-30-2014  |  1 |04-30-2013|40 
3  |03-24-2014  |  1 |10-12-2018|12 
4  |05-28-2014  |  2 |11-17-2013|55 

期望的結果是加入兩列並返回一行。我遇到的問題是,如果我使用示例數據加入兩個列是相等的,那麼只有第一行會返回。如果我將ID列設置爲相等並使用< =,則多行將返回ID 1,這是不希望的。我無法使用最大日期,因爲某些字段包含將來的日期,在兩個日期字段相等之前不應返回記錄。在示例數據中,所需的結果將返回數字25和55.所以基本上我需要加入ID列相同和日期字段相等,但如果表B中沒有相同的日期,則返回最新日期的編號,假設它不是未來的日期。

希望這是有道理的。提前致謝。

+0

那麼,結果如何?你有沒有得到一個適合你的答案? – ngreen 2014-10-31 16:40:43

+0

我對這個大規模的延遲表示歉意......它在一段時間裏倒下了。我最終使用ROW OVER的相關子查詢來分割結果,只抓取所需結果。 – user2820853 2015-07-16 19:17:47

回答

0

我會建議使用相關子查詢或申請操作。下面是方法:

select a.*, b.* 
from tablea a outer apply 
    (select top 1 b.* 
     from tableb b 
     where b.id = a.id and 
      b.date <= a.date 
     order by b.date desc 
    ) b; 
0

試試這個:

-- build sample data 
create table #TableA(
    ID int, 
    [Date] smalldatetime 
) 
create table #TableB(
    ID int, 
    [Date] smalldatetime, 
    number int 
) 

insert into #TableA 
select 1, '1/1/2014' union all 
select 2, '1/30/2014' union all 
select 3, '3/24/2014' union all 
select 4, '5/28/2014' 

insert into #TableB 
select 1, '1/1/2014', 25 union all 
select 1, '4/30/2013', 40 union all 
select 1, '10/12/2018', 12 union all 
select 2, '11/17/2013', 55 

-- start 
;with cte(ID, [Date], Number, rn) as(
    select 
     a.id, 
     b.date, 
     number, 
     row_number() over(
      partition by a.id 
      order by 
       case 
        when a.date = b.date then dateadd(d, 1, getdate()) 
        else b.date 
       end 
      desc     
     ) 
    from #TableA a 
    inner join #TableB b 
     on b.id = a.id 
    where 
     a.date <= getdate() 
     and b.date <= getdate() 
) 
select 
    id, 
    date, 
    number 
from cte where rn = 1 
-- end 

-- drop temp tables 
drop table #TableA 
drop table #TableB 
1

是啊,這是一個有點棘手,但這個應該這樣做:在目前

with equalvalues as (
select b.* from a 
inner join b on a.ID=b.ID and a.adate=b.bdate 
), 
latestdates as (
select b.id, MAX(b.bdate) as maxbdate 
from b 
where b.bdate<=GETDATE() 
group by b.ID 
) 
select number from equalvalues 
union all 
select b.number from b 
inner join latestdates d on d.ID=b.ID and d.maxbdate=b.bdate 
where b.ID not in (select ID from equalvalues) 
0

我沒有可用的SQL Server實例給我,所以我m會發布適用於PostgreSQL的語法;它應該翻譯得相當好。我的目標是獲得Table B的主鍵,然後使用主鍵選擇該行。它適用於您提供的樣本數據。我不知道你有什麼規則來確定一個日期是否過於遙遠,所以我輸入了一個硬編碼的日期,它可以輕鬆地交換一個綁定變量。

with KB as (
    select id as id, max(dt) as dt 
    from (
    select B.id, B.dt, B.num 
    from B 
     inner join A on A.id = B.id and A.dt = B.dt 
    union 
    select B.id, max(B.dt), B.num from B 
     inner join A on A.id = B.id and A.dt != B.dt 
    where B.dt < convert(datetime, '2014.10.313', 102) 
    group by B.id, B.num 
) subquery 
    group by id 
) 
select B.id, B.dt, B.num 
from B 
    inner join KB on KB.id = B.id and X.dt = B.dt; 

工作原理:

第一內查詢只是一味地抓住精確匹配。他們需要,爲什麼不呢?第二個內部查詢抓取所有不精確的匹配(ID相等,但日期不相等)。一旦相等的集合和不相等的集合組合起來,外部查詢爲每個ID挑選最新日期(max)。在這一點上,每行必須有一個單一的日期爲每個ID,所以唯一要做的就是獲得完全匹配的行。

我不知道這個解釋計劃是什麼樣的。它不應該壞,但我可能是完全錯誤的。