我正在尝试使用SQL 2012基于以下数据生成特定字符串
| Id | Activity | Year |
|----|----------|------|
| 01 | AAAAA | 2008 |
| 01 | AAAAA | 2009 |
| 01 | AAAAA | 2010 |
| 01 | AAAAA | 2012 |
| 01 | AAAAA | 2013 |
| 01 | AAAAA | 2015 |
| 01 | BBBBB | 2014 |
| 01 | BBBBB | 2015 |
结果需要看起来像;
| 01 | AAAAA | 2008-2010, 2012-2013, 2015 |
| 01 | BBBBB | 2014-2015 |
非常感谢任何有关如何实现这一目标的想法。
答案 0 :(得分:6)
使用ROW_NUMBER
与group the contiguous years和FOR XML PATH('')
进行字符串连接。
WITH Cte AS(
SELECT *,
grp = year - ROW_NUMBER() OVER(PARTITION BY id, activity ORDER BY year)
FROM tbl
)
SELECT
id,
activity,
x.years
FROM Cte c
CROSS APPLY(
SELECT STUFF((
SELECT ', ' + CONVERT(VARCHAR(4), MIN(year)) +
CASE
WHEN MIN(year) <> MAX(year) THEN '-' + CONVERT(VARCHAR(4), MAX(year))
ELSE ''
END
FROM Cte
WHERE
id = c.id
ANd activity = c.activity
GROUP BY id, activity, grp
FOR XML PATH('')
), 1, 2, '')
)x(years)
GROUP BY id, activity, x.years
结果:
| id | activity | years |
|----|----------|----------------------------|
| 01 | AAAAA | 2008-2010, 2012-2013, 2015 |
| 01 | BBBBB | 2014-2015 |
答案 1 :(得分:1)
您可以使用XML路径(用于连接组值)和按 id 和 anctivity 进行分组:
MS SQL Server架构设置:
create table tbl (id varchar(2),activity varchar(10),year int);
insert into tbl values
( '01' ,'AAAAA', 2008 ),
( '01' ,'AAAAA', 2009 ),
( '01' ,'AAAAA', 2010 ),
( '01' ,'AAAAA', 2012 ),
( '01' ,'AAAAA', 2013 ),
( '01' ,'AAAAA', 2015 ),
( '01' ,'BBBBB', 2014 ),
( '01' ,'BBBBB', 2015 )
<强>查询强>:
select
id, activity,
stuff(
(select distinct ',' + cast(year as varchar(4))
from tbl
where id = t.id and activity=t.activity
for xml path (''))
, 1, 1, '') as years
from tbl AS t
group by id,activity
<强> Results 强>:
| id | activity | years |
|----|----------|-------------------------------|
| 01 | AAAAA | 2008,2009,2010,2012,2013,2015 |
| 01 | BBBBB | 2014,2015 |
在评论后进行编辑并注意到所需的输出:
如果您还希望将连续分组如 2008-2009 那么您需要额外的分组(每组中年份和等级的差异将为您提供一个独特的嵌套组):
<强>查询强>:
with cte1 as
(
select r = year - (rank() over(partition by id,activity
order by year)),
id,activity,year from tbl
)
,cte2 as
(
select
id, activity, cast(min(year) as varchar(4)) +
case when min(year)<>max(year)
then '-' + cast(max(year) as varchar(4))
else '' end as years
from cte1
group by r,id,activity
)
select
id, activity,
stuff(
(select distinct ',' + years
from cte2
where id = t.id and activity=t.activity
for xml path (''))
, 1, 1, '') as years
from cte2 AS t
group by id,activity
<强> Results 强>:
| id | activity | years |
|----|----------|--------------------------|
| 01 | AAAAA | 2008-2010,2012-2013,2015 |
| 01 | BBBBB | 2014-2015 |
答案 2 :(得分:0)
因为它的sql-2012我使用CONCAT修改了天才@FelixPamittan的答案帖子。
;WITH Cte AS(
SELECT *,
grp = year - ROW_NUMBER() OVER(PARTITION BY id, activity ORDER BY year)
FROM #TEMP
)
SELECT DISTINCT
id,
activity,
(SELECT STUFF((SELECT ', ' + CONCAT(MIN(year),
CASE
WHEN MIN(year) <> MAX(year) THEN CONCAT('-', MAX(year))
ELSE ''
END)
FROM Cte
WHERE
id = c.id
ANd activity = c.activity
GROUP BY id, activity, grp
FOR XML PATH('')
), 1, 2, '')) AS YEARS
FROM Cte c