2013-07-05 61 views
4

我有兩個表Names和Name_ids,如下所示。如何爲以下輸出編寫查詢?

平臺:SQL Server 2005/2008。

Names table: 
    Nam        ID 
    -------------------------------- ----------- 
    A        1 
    B        2 
    C        3 
    D        4 
    E        5 
    F        6 
    G        7 
    H        8 

name_ids table 

ID 
----------- 
3 
6 
8 

我想產生以下輸出接合這些表。

Nam        Nam_ID  ID 
-------------------------------- ----------- ----------- 
A        1   NULL 
B        2   NULL 
C        3   3 
D        4   3 
E        5   3 
F        6   6 
G        7   6 
H        8   8 

該邏輯將nam_id與id匹配,如果nam_id小於任何id,則返回NULL。 如果nam_id大於或等於id,則返回id。這是抓住。在上面的例子中,對於F,我們不應該返回F,6,3組合,但是我們應該只返回匹配的F,6,6。當找到匹配的項目像6,6時,它應該跳過其他匹配,如6,3。之後使用7,6而不是7,3。 如何爲上面的代碼寫一個sql查詢?查詢時間密集且需要快速執行。

Scripts: 
Create table Names(Nam nvarchar(32), ID int); 

insert into names values('A', 1); 
insert into names values('B', 2); 
insert into names values('C', 3); 
insert into names values('D', 4); 
insert into names values('E', 5); 
insert into names values('F', 6); 
insert into names values('G', 7); 
insert into names values('H', 8); 


Create table name_ids(ID int); 
insert into name_ids values(3); 
insert into name_ids values(6); 
insert into name_ids values(8); 

請幫忙。

更新: 嘿,大家好,非常感謝您提供解決方案的努力。現在我很困惑選擇性能最好的查詢。我選擇了幾個並試圖用非常大的結果集來分析性能。

+0

你做解釋的一個很好的工作,但我們想看看你都試過到目前爲止 – epoch

+0

@vikiii,4大於3,但小於6 – Pavan

回答

1
select a.Nam, a.ID Nam_ID, 
     isnull(b.ID,(select max(id) from name_ids where id<a.id)) 
from Names a left outer join name_ids b 
on (a.ID = b.ID); 

See DEMO here

+1

downvoters不知道SQL – chetan

+3

我米不是downvoter,但我可能猜測dowvotes來自你以前的版本,這是錯誤的。 –

+1

第一步應該明白,第二個建議/評論,最後倒票〜倒下投票者應該在倒票前花費一些時間:@RaphaëlAlthaus –

1
select Nam,id, 
(select TOP 1 id 
     from name_ids 
     where name_ids.id<= Names.id 
     order by name_ids.id desc) 
from Names order by id 

SQLFiddle demo

5
select n.Nam, 
CASE WHEN ni.ID IS NULL THEN (SELECT MAX(ID) from name_ids n1 where 
           n1.ID < n.ID) 
         ELSE ni.ID 
         END 
from Names n 
left join name_ids ni on n.ID = ni.ID 

SqlFiddle

+0

+1與SqlFiddle – WiiMaxx

+0

證明你有單一版本仍然downvoted! –

0

很簡單的事:

SELECT A.Nam , A.Nam_ID , B.ID 
FROM NAMES AS A 
OUTER APPLY 
(
    SELECT MAX(ID) AS ID 
    FROM NAME_IDS AS B WHERE A.ID >= B.ID 
) AS B 

我認爲這是更簡單的內聯查詢版本。

+0

你試過這個嗎? –

+0

[SQLFiddle說不的](http://sqlfiddle.com/#!6/e582a/15) – WiiMaxx

+0

是的,我已經檢查過,但有一些問題與小提琴,我檢查了SQL Server管理工作室2008年。檢查http://prntscr.com/1dobbm –

2

請檢查我的嘗試:

SELECT 
    DISTINCT Nam, 
    a.ID Nam_ID, 
    MAX(b.ID) OVER (PARTITION BY Nam) ID 
FROM 
    Names a LEFT JOIN name_ids b 
     ON a.ID>=b.ID 
+0

[SQLFiddle proofed:]](http://sqlfiddle.com/#!3/e582a/19) – WiiMaxx

+0

感謝您加入Fiddle @WiiMaxx :) – TechDo

1

嘗試:

with cte as 
(select i.*, row_number() over (order by id) rn 
from name_ids i) 
select na.Nam, na.id Nam_id, s.id 
from Names na 
left join (select c.id, n.id next_id 
      from cte c 
      left join cte n on c.rn+1 = n.rn) s 
     on na.id >= s.id and na.id < coalesce(s.next_id, na.id+1) 

SQLFiddle here

1
select names.Nam, names.ID, max(name_ids.ID) 
from names left join name_ids 
on names.ID >= name_ids.id 
group by names.Nam, names.ID 
+0

[SQLFiddle proofed:)](http://sqlfiddle.com/# !6/e582a/16) – WiiMaxx