如何为以下输出编写查询?

时间:2013-07-05 11:40:26

标签: sql sql-server

我有两个表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,6我们不应该返回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);

请帮忙。

更新: 嘿伙计们,非常感谢您提供解决方案的努力。现在我很困惑,选择性能最佳的查询。我已经捡到了一些并试图用非常大的结果集来分析性能。

7 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分: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

答案 4 :(得分: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

答案 5 :(得分: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

答案 6 :(得分: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

我认为这是更简单的内联查询版本。