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,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);

请帮忙。

更新:我非常感谢您为提供解决方案所做的努力。现在我很困惑选择性能最好的查询。我收集了一些并尝试使用非常大的结果集来分析性能。

4

7 回答 7

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

于 2013-07-05T11:46:50.480 回答
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
于 2013-07-05T11:50:41.753 回答
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);

在此处查看演示

于 2013-07-05T11:43:00.207 回答
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 演示

于 2013-07-05T11:46:44.910 回答
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在这里

于 2013-07-05T11:51:24.740 回答
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
于 2013-07-05T11:52:24.370 回答
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

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

于 2013-07-05T11:49:35.950 回答