我正在尝试将数据从两列(一个带有文本,一个带有数字)转换为一个范围。
我已经搜索过,无法找到适用于此需求解决方案的内容:
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
非常感谢任何帮助
答案 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)