1

私は次のようなデータベーステーブルを持っています:

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

どうやってやるの?

*例を簡略化するために編集

4

2 に答える 2

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 ごとに1回だけ関数を呼び出す方が効率的であるため、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
于 2012-10-02T03:37:07.493 に答える
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;

ここにSQLFiddleのデモがあります

ただし、イベントループでサイクルを処理する方法がわかりません。

于 2012-10-02T06:37:31.807 に答える