由非重叠范围指定的SQL连接键

时间:2015-03-10 14:30:26

标签: sql sql-server join sql-server-2012

我想加入一个带有range定义的键的表。像这样的经典方法非常慢:

SELECT A.ID, B.Index 
FROM table1 as A 
INNER JOIN  table2 as B
ON ID.Key BETWEEN B.IDfrom AND B.IDto

我有这组表: Key defined by ranges

  • ID和索引都定义为群集的主键。我不是 db的所有者,所以我没有权利添加或更改主要的 外键。
  • IDfromIDto定义的范围不重叠。所以 从理论上讲,只有一列就足以确定是否有ID 落入指定的范围。
  • 当然,表1和表2还有其他列,而不仅仅是那些列 在一张照片上。

由于我的表格很大,所提出的经典解决方案非常慢,因为SQL不知道IDfrom是按升序排序的,而且它必须检查Table2的每一行。

如果我缩小Table1的ID范围以使其说1000行,则查询工作得非常快。我能看到的唯一绝望的方法是在循环中处理所有内容,确定ID范围从1到1000,然后从1001到2000,依此类推。对我的问题没有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

我认为

The ranges defined by IDfrom and IDto do not overlap. So theoretically just one column would be enough to determine if ID falls into a specified range.

您可以尝试子查询,但我不知道它是否会更快:

DECLARE @Table1 TABLE ( ID INT )
DECLARE @Table2 TABLE
    (
      ID INT ,
      IDFrom INT ,
      IDTo INT
    )

INSERT  INTO @Table1
VALUES  ( 1 ),
        ( 2 ),
        ( 3 ),
        ( 4 ),
        ( 5 ),
        ( 6 ),
        ( 7 ),
        ( 8 ),
        ( 9 ),
        ( 10 ),
        ( 11 ),
        ( 12 )

INSERT  INTO @Table2
VALUES  ( 1, 1, 3 ),
        ( 2, 4, 4 ),
        ( 3, 5, 10 ),
        ( 4, 11, 12 )

SELECT  t1.ID AS ID1,
        ( SELECT    MIN(ID)
          FROM      @Table2 t2
          WHERE     t2.IDTo >= t1.ID
        ) AS ID2
FROM    @Table1 t1

输出:

ID1 ID2
1   1
2   1
3   1
4   2
5   3
6   3
7   3
8   3
9   3
10  3
11  4
12  4

答案 1 :(得分:1)

你可以尝试这个技巧。交错数据然后使用累积最大值。

select id, table2index
from (select id, max(index) over (order by id) as table2index, index
      from (select id, NULL as index
            from table1
            union all
            select index, index as index
            from table2
           ) tt
      ) tt
where index is null;

注意:这假设table2中的索引正在增加。此外,这需要SQL Server 2012+。并且,我保留了您的列名,即使它们会导致错误(index是保留字)。