我有一个如下所示的数据库表:
EVENT_ID TEXT_FRO TEXT_TO
55001 05
55001 05 10
55001 10 15
55001 15 20
55001 20 30
56215 06 11
56215 11 22
我需要编写一个查询(或SP)来生成一个结果集,列出每个不同event_ID的所有动作,如下所示:
Event ID Movements
55001 05 10 15 20 30
56215 06 11 22
我该怎么做?
*编辑以简化示例
答案 0 :(得分:1)
如果使用函数和光标,这是非常简单的:
use tempdb
go
create table tmp (
EVENT_ID int,
TEXT_FRO varchar(10),
TEXT_TO varchar(10)
)
go
insert into tmp values
(55001, NULL, '05'),
(55001, '05', '26'),
(55001, '26', '28'),
(55001, '28', '27'),
(55001, '27', '26'),
(55001, '26', '27'),
(55001, '27', '28'),
(55001, '28', '30'),
(55001, '30', '40'),
(56215, '06', '11'),
(56215, '11', '22')
go
您必须创建一个函数来组合连接字符串:
create function fnConcat (@id int) returns varchar(255) as
begin
declare @rtn varchar(255) = '', @fro varchar(10), @to varchar(10), @cnt int = 1
declare cr cursor local for
select TEXT_FRO, TEXT_TO
from tmp
where EVENT_ID = @id
open cr
fetch next from cr into @fro, @to
while @@fetch_status = 0
begin
if @cnt = 1 and @fro is not null
set @rtn = @rtn + @fro + ' '
set @rtn = @rtn + @to + ' '
set @cnt = @cnt + 1
fetch next from cr into @fro, @to
end
close cr
deallocate cr
set @rtn = left(@rtn, datalength(@rtn) - 1)
return @rtn
end
go
如果您只为每个唯一的EVENT_ID调用一个时间,效率更高,因此我们在子查询中选择distinct
EVENT_ID:
select x.EVENT_ID as [Event ID], dbo.fnConcat(x.EVENT_ID) as Movements
from (
select distinct EVENT_ID
from tmp
) as x
go
然后清理:
drop table tmp
go
drop function fnConcat
go
结果如下:
Event ID Movements
----------- ---------------------------
55001 05 26 28 27 26 27 28 30 40
56215 06 11 22
答案 1 :(得分:1)
您可以使用递归公用表表达式执行此操作。
出于测试目的,我在测试表中添加了一列,用于标识事件的顺序,以便能够识别第一个:
create table movements
(
event_id INTEGER,
text_fro VARCHAR(10),
text_to VARCHAR(10),
sort_ord INTEGER
);
insert into movements (event_id, text_fro, text_to, sort_ord)
values
(55001,null,'05',1),
(55001,'05','10',2),
(55001,'10','15',3),
(55001,'15','20',4),
(55001,'20','30',5),
(56215,'06','11',1),
(56215,'11','22',2)
;
with mvt as (
select m1.event_id as root_id,
m1.event_id,
cast(coalesce(m1.text_fro,'') + ' ' + m1.text_to as varchar(8000)) as path,
m1.text_fro,
m1.text_to,
m1.sort_ord
from movements m1
where m1.text_fro is null
or m1.sort_ord = (select min(sort_ord) from movements m2 where m1.event_id = m2.event_id)
union all
select p.root_id,
c.event_id,
p.path + ' ' + c.text_to,
c.text_fro,
c.text_to,
c.sort_ord
from movements c
join mvt p on p.text_to = c.text_fro
)
select root_id, max(ltrim(path)) as movements
from mvt
group by root_id;
我不知道如何处理事件循环中的循环。