爆炸整数范围以加入SQL

时间:2013-05-17 22:38:48

标签: sql sql-server-2008 tsql join

我有一个表在一个字段中存储一系列整数,有点像打印范围,(例如“1-2,4-7,9-11”)。该字段也可以包含一个数字。

我的目标是将此表连接到具有离散值而非范围的第二个表。

因此,如果第一个表包含

1-2,5
9-15
7

表二包含

1
2
3
4
5
6
7
8
9
10

联接的结果将是

1-2,5   1
1-2,5   2
1-2,5   5
7       7
9-15    9
9-15    10

在SQL Server 2008 R2中工作。

4 个答案:

答案 0 :(得分:7)

使用string split function of your choice分隔逗号。找出最小/最大值并使用之间的连接。

SQL Fiddle

MS SQL Server 2012架构设置

create table T1(Col1 varchar(10))
create table T2(Col2 int)

insert into T1 values
('1-2,5'),
('9-15'),
('7')

insert into T2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

查询1

select T1.Col1,
       T2.Col2
from T2
  inner join (
              select T1.Col1,
                     cast(left(S.Item, charindex('-', S.Item+'-')-1) as int) MinValue,
                     cast(stuff(S.Item, 1, charindex('-', S.Item), '') as int) MaxValue
              from T1
                cross apply dbo.Split(T1.Col1, ',') as S
             ) as T1
    on T2.Col2 between T1.MinValue and T1.MaxValue

<强> Results

|  COL1 | COL2 |
----------------
| 1-2,5 |    1 |
| 1-2,5 |    2 |
| 1-2,5 |    5 |
|  9-15 |    9 |
|  9-15 |   10 |
|     7 |    7 |

答案 1 :(得分:4)

就像每个人都说的那样,在SQL Server中本地执行是一件痛苦的事。如果您必须,那么我认为这是正确的方法。

首先确定解析字符串的规则,然后将过程分解为明确定义和理解的问题 根据你的例子,我认为这是一个过程:

  1. 将字符串中的逗号分隔值分隔为行
  2. 如果数据包含短划线,那么它已完成(这是一个独立的值)
  3. 如果确实包含短划线,请解析短划线的左右两侧
  4. 鉴于左侧和右侧(范围)确定它们之间的所有值为行
  5. 我会创建一个临时表来填充解析结果,其中需要两列:
    SourceRowID INT, ContainedValue INT

    和另一个用于中间处理:
    SourceRowID INT, ContainedValues VARCHAR

    使用类似这样的CTE将逗号分隔的值解析为自己的行步骤1现在是一个定义明确且易于理解的问题

    Turning a Comma Separated string into individual rows

    所以你的结果来源于 '1-2,5'
    将是:
        '1-2'
        '5'

    从那里,来自该处理表的SELECT字段包含短划线。 第2步现在是一个定义明确且易于理解的问题这些是独立的数字,可以直接进入结果临时表。结果表还应该获得原始行的ID引用。

    接下来是使用CHARINDEX解析短划线左侧和右侧的值以找到它,然后根据需要调整相应的LEFTRIGHT函数。这将为您提供起始值和结束值。

    以下是完成此操作的相关问题第3步现在是一个定义明确且易于理解的问题

    T-SQL substring - separating first and last name

    现在您已将起始值和结束值分开。使用可以爆炸此范围的其他功能。 第4步现在是一个定义明确且易于理解的问题

    SQL: create sequential list of numbers from various starting points

    SELECT all N between @min and @max

    What is the best way to create and populate a numbers table?

    并且,也将它插入临时表。

    现在您应该拥有的是一个临时表,其中包含爆炸范围内的每个值。

    现在只需JOIN到值的另一个表,然后到ID参考的源表,你就在那里。

答案 2 :(得分:0)

我的建议是在范围表中再添加一个字段和更多记录。具体来说,主键是整数,另一个字段是范围。记录看起来像这样:

number    range
1         1-2,5
2         1-2,5
3         na
4         na
5         1-2,5

话虽如此,这仍然是相当有限的,因为一个数字只能有一个范围。如果您想要彻底,请在数字和范围之间建立多对多的关系。

答案 3 :(得分:0)

据我所知,最佳选择如下:

创建一个表值函数,接受您的范围并将它们转换为整数的集合。所以1-3,5会返回:

1
2
3
5

然后使用这些结果加入其他表。我手边没有确切的功能,但this one似乎是一个很好的开始。