【问题标题】:Get Multiple rows from multiple values (columns) in SQL Server 2008 R2从 SQL Server 2008 R2 中的多个值(列)获取多行
【发布时间】:2017-07-06 15:58:22
【问题描述】:

我有这张桌子

+-----+------+--------+--------+
| ID  | Name |  Start |   End  |
+-----+------+--------+--------+
| 20  | Mike |   1    |    3   |
| 21  | Luke |   4    |    7   |
+-----+------+--------+--------+ 

我想根据每个人的范围(开始/结束)生成所有行。

结果应该是这样的

+-----+------+-----------------+
| ID  | Name |    Start_End    |
+-----+------+-----------------+
| 20  | Mike |        1        |
| 20  | Mike |        2        |
| 20  | Mike |        3        |
| 21  | Luke |        4        |
| 21  | Luke |        5        |
| 21  | Luke |        6        |
| 21  | Luke |        7        |
+-----+------+--------+--------+ 

为了获得基于开始和结束列的唯一值,我有这个功能

CREATE FUNCTION [dbo].[ufn_SplitRange] (@Start INT, @End INT)  
RETURNS TABLE  
AS  
RETURN   
(  
    SELECT  TOP (@End - @Start+1) ROW_NUMBER() OVER (ORDER BY S.[object_id])+(@Start - 1) [Start_End]
    FROM    sys.all_objects S WITH (NOLOCK)
); 

上述函数返回(基于麦克范围1-3)的输出:

1
2
3

我一直在尝试几种方法,但找不到合适的解决方案,这似乎是一项非常常见的任务,但却是一项棘手的任务。

非常感谢任何意见

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql sql-server-2008-r2


    【解决方案1】:

    使用cross apply():

    select t.Id, t.Name, x.Start_End
    from t
      cross apply dbo.ufn_SplitRange(t.Start,t.[End]) as x
    

    rextester 演示:http://rextester.com/FVA48693

    返回:

    +----+------+-----------+
    | Id | Name | Start_End |
    +----+------+-----------+
    | 20 | Mike |         1 |
    | 20 | Mike |         2 |
    | 20 | Mike |         3 |
    | 21 | Luke |         4 |
    | 21 | Luke |         5 |
    | 21 | Luke |         6 |
    | 21 | Luke |         7 |
    +----+------+-----------+
    

    【讨论】:

    • @Carlos 乐于助人!
    【解决方案2】:

    您可以使用如下的计数表:

    Select Id, Name, Start_end from #Values
    cross apply (
            Select top ([end] - [start] +1) Start_end = [start] + Row_number() over (order by (Select NULL))-1
            from master..spt_values s1, master..spt_values s2
            ) a
    

    输出:

    +----+------+----+
    | Id | Name | RN |
    +----+------+----+
    | 20 | Mike |  1 |
    | 20 | Mike |  2 |
    | 20 | Mike |  3 |
    | 21 | Luke |  4 |
    | 21 | Luke |  5 |
    | 21 | Luke |  6 |
    | 21 | Luke |  7 |
    +----+------+----+
    

    【讨论】:

      【解决方案3】:

      你可以像这样使用recursive cte

      DECLARE @SampleData AS TABLE 
      (
          Id int,
          Name varchar(10),
          Start int,
          [End] int
      )
      
      INSERT INTO @SampleData
      (
          Id,
          Name,
          Start,
          [End]
      )
      VALUES
      (1,'Mike',1,3),
      (2,'Luke',4,7)
      
      ;WITH temp AS
      (
          SELECT Id, sd.Name, sd.Start , sd.[End]
          FROM @SampleData sd
      
          UNION ALL
      
          SELECT t.Id, t.Name, t.Start + 1, t.[End]
          FROM temp t
          WHERE t.Start < t.[End]
      )
      SELECT t.Id, t.Name, t.Start AS [Start_End]
      FROM temp t
      ORDER BY t.Id
      OPTION (MAXRECURSION 0)
      

      演示链接:http://rextester.com/AFNYFW81782

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 1970-01-01
        • 2021-02-03
        • 2012-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多