将两个文本/数字数据转换为范围

时间:2015-07-16 01:02:57

标签: sql-server-2008-r2

我正在尝试将数据从两列(一个带有文本,一个带有数字)转换为一个范围。

我已经搜索过,无法找到适用于此需求解决方案的内容:

Table:
ColumnA Nvarchar(50) 
ColumnB Int

表样本:

ColumnA  ColumnB 
AA       1    
AA       2    
AA       3    
AA       4    
AA       5    
AB       1    
AB       2    
AB       3
AB       4

期望的输出:

AA:1-5, AB:1-4

非常感谢任何帮助

2 个答案:

答案 0 :(得分:1)

注意我假设您提出问题的原因是您可能已经破坏了范围,并且您不是简单地为每个ColumnA寻找最小/最大ColumnB。

如果你问我,这种类型的东西最好是在中间层的代码中处理,或者直接在表示层中处理。在查询中按行(ColumnA,ColumnB)对行进行排序,然后在读取行时通过一次传递获得所需的结果 - 通过将当前值与前一行进行比较,并在ColumnA更改或ColumnB为时输出一行不相邻。

但是,如果您一直想在SQL中执行此操作,则可以使用递归CTE。基本前提是将每一行与相邻行相关联,并在继续时保持ColumnB的起始值。相邻行被定义为具有相同ColumnA值的行和下一个ColumnB值(即前一行+ 1)。

以下应该做的事情:

;with cte as (
     select a.ColumnA, a.ColumnB, a.ColumnB as rangeStart
     from myTable a
     where not exists ( --make sure we don't keep 'intermediate rows' as start rows
         select 1
         from myTable b
         where b.ColumnA = a.ColumnA
         and b.ColumnB = a.ColumnB - 1
     )
     union all
     select a.ColumnA, b.ColumnB, a.rangeStart
     from cte a
     join myTable b on a.ColumnA = b.ColumnA
         and b.ColumnB = a.ColumnB + 1 --correlate with 'next' row
)
select ColumnA, rangeStart, max(ColumnB) as rangeEnd
from cte
group by ColumnA, rangeStart

并提供您的示例数据indeed it does

对于踢,here is another Fiddle with data having gaps in ColumnB

答案 1 :(得分:0)

通过做一些数学运算来注意连续值的group by子句。

DECLARE @Data table (ColumnA Nvarchar(50), ColumnB Int)

INSERT @Data VALUES 
('AA', 1),
('AA', 2),
('AA', 3),
--('AA', 4),
('AA', 5),
('AB', 1),
('AB', 2),
('AB', 3),
('AB', 4)

;WITH Ordered AS 
(
    SELECT 
      ROW_NUMBER() OVER (PARTITION BY ColumnA ORDER BY ColumnB) AS Seq, 
      * 
    FROM @Data
)
SELECT 
  ColumnA, 
  CASE 
    WHEN 1 = 0 THEN ''
    -- if the ColumnA only has 1 row, the display is 1-1? or just 1?
    --WHEN MIN(ColumnB) = MAX(ColumnB) THEN CONVERT(varchar(10), MIN(ColumnB)) 
    ELSE CONVERT(varchar(10), MIN(ColumnB)) + '-' + CONVERT(varchar(10), MAX(ColumnB))
  END AS Range
FROM Ordered 
GROUP BY 
  ColumnA, 
  ColumnB - Seq -- The math
ORDER BY ColumnA, MIN(ColumnB)

SQL Fiddle