0

以下のように、データをフォーマットに変換する作業をしています。 私は最終的にそれをやったが、どのように改善できるか知りたい。 最終的な解決策への私のステップが含まれています。 正しい結果が最終クエリによって生成されます。フォーマット:Location1:Date1:​​Code1、Code2、Code ...:Date2:Code1、Code2、Code ...:Date ...:Code ... // Location2:Date ...:Code ...//場所... ...日付...コード...SQL:階層型(一対多)データから平らな文字列を作成する

結果: Loc1:2016-01-01:Alpha:2016-01-03:Bravo、Charlie、Charlie:2016-01-04:アルファ、アルファ:2016年1月5日:アルファ、デルタ、エコー// LOC2:2016年1月1日:ブラボー、デルタ// LOC3:2016年1月2日:ブラボー

declare @Operation table (
ID int identity not NULL, 
ItemID int, 
LocationID int, 
[Date] date 
) 

declare @Location table (
ID int identity not NULL, 
Name varchar(200) 
) 

declare @LineItem table (
ID int identity not NULL, 
OperationID int, 
CodeID int 
) 

declare @Code table (
ID int identity not NULL, 
Value varchar(200) 
) 

insert @Operation 
values 
(1, 1, '2016-01-01'), 
(1, 2, '2016-01-01'), 
(1, 1, '2016-01-03'), 
(1, 1, '2016-01-04'), 
(1, 3, '2016-01-02'), 
(1, 1, '2016-01-05') 

insert @Location 
values 
('Loc1'), 
('Loc2'), 
('Loc3') 

insert @LineItem 
values 
(1, 1), 
(2, 4), 
(2, 2), 
(3, 3), 
(3, 2), 
(3, 3), 
(4, 1), 
(4, 1), 
(5, 2), 
(6, 5), 
(6, 4), 
(6, 1) 

insert @Code 
values 
('Alpha'), 
('Bravo'), 
('Charlie'), 
('Delta'), 
('Echo') 

select 
* 
from @Operation vo 
join @Location vl 
on vl.ID = vo.LocationID 
join @LineItem vli 
on vli.OperationID = vo.ID 
join @Code vc 
on vc.ID = vli.CodeID 

select 
vl.Name as OpLocation, 
vo.[Date] as OpDate, 
OpCodes 
from @Operation vo 
join @Location vl 
on vl.ID = vo.LocationID 
cross apply (
select 
    stuff(List, 1, 1, '') as OpCodes 
from (
    select 
     ',' + vc.Value 
    from @LineItem vli 
    join @Code vc 
     on vc.ID = vli.CodeID 
    where vli.OperationID = vo.ID 
    order by vc.Value 
    for xml path('') 
    ) as X(List) 
) as xCodes 

select 
vl.Name as OpLocation, 
vo.[Date] as OpDate, 
OpCodes 
from @Operation vo 
join @Location vl 
on vl.ID = vo.LocationID 
cross apply (
select 
    stuff(List, 1, 1, '') as OpCodes 
from (
    select 
     ',' + vc.Value 
    from @LineItem vli 
    join @Code vc 
     on vc.ID = vli.CodeID 
    where vli.OperationID = vo.ID 
    order by vc.Value 
    for xml path('') 
    ) as X(List) 
) as xCodes 
group by vl.Name, vo.[Date], OpCodes 

select 
vl.Name as OpLocation, 
OpDateAndCodes 
from @Operation vo 
join @Location vl 
on vl.ID = vo.LocationID 
cross apply (
select 
    convert(varchar(10), [Date], 21) + ':' + OpCodes as OpDateAndCodes 
from (
    select 
     stuff(List, 1, 1, '') as OpCodes 
    from (
     select 
      ',' + vc.Value 
     from @LineItem vli 
     join @Code vc 
      on vc.ID = vli.CodeID 
     where vli.OperationID = vo.ID 
     order by vc.Value 
     for xml path('') 
     ) as X(List) 
    ) as Codes 
) as xODC 
group by vl.Name, OpDateAndCodes 

;with cte as (
select 
    vl.Name as Location, 
    OpDateAndCodes 
from @Operation vo 
join @Location vl 
    on vl.ID = vo.LocationID 
cross apply (
    select 
     convert(varchar(10), [Date], 21) + ':' + OpCodes as OpDateAndCodes 
    from (
     select 
      stuff(List, 1, 1, '') as OpCodes 
     from (
      select 
       ',' + vc.Value 
      from @LineItem vli 
      join @Code vc 
       on vc.ID = vli.CodeID 
      where vli.OperationID = vo.ID 
      order by vc.Value 
      for xml path('') 
      ) as X(List) 
     ) as Codes 
    ) as xODC 
) 
select 
    Location, 
    stuff(List, 1, 1, '') as ODC 
from cte cte1 
cross apply (
    select 
     ':' + OpDateAndCodes 
    from cte cte2 
    where cte2.Location = cte1.Location 
    for xml path('') 
    ) as X(List) 

//SOLUTION 
;with cte as (
select 
    vl.Name as Location, 
    OpDateAndCodes 
from @Operation vo 
join @Location vl 
    on vl.ID = vo.LocationID 
cross apply (
    select 
     convert(varchar(10), [Date], 21) + ':' + OpCodes as OpDateAndCodes 
    from (
     select 
      stuff(List, 1, 1, '') as OpCodes 
     from (
      select 
       ',' + vc.Value 
      from @LineItem vli 
      join @Code vc 
       on vc.ID = vli.CodeID 
      where vli.OperationID = vo.ID 
      order by vc.Value 
      for xml path('') 
      ) as X(List) 
     ) as Codes 
    ) as xODC 
) 
select 
    distinct 
     stuff(List, 1, 2, '') 
from cte cte1 
cross apply (
    select 
     '//' + OpLocationDateAndCodes 
    from (
     select 
      distinct 
       Location + ':' + stuff(List, 1, 1, '') as OpLocationDateAndCodes 
     from cte cte2 
     cross apply (
      select 
       ':' + OpDateAndCodes 
      from cte cte3 
      where cte3.Location = cte2.Location 
      for xml path('') 
      ) as X(List) 
     ) as OLDC 
    for xml path('') 
    ) as X(List) 

答えて

0

は、ここで私はアプローチですサブクエリを使用した単一のクエリを使用することができました。出力はあなたのコードと正確に一致します。

SELECT STUFF((
    SELECT 
     '//' + L.Name 
     + (
      SELECT ':' + CONVERT(VARCHAR(50), O.Date) + ':' 
       + STUFF((
        SELECT ',' + C.Value 
        FROM @LineItem LI 
         INNER JOIN @Code C 
          ON C.ID = LI.CodeID 
        WHERE LI.OperationID = O.ID 
        FOR XML PATH('')), 1, 1, '') 
      FROM @Operation O 
      WHERE O.LocationID = L.ID 
      FOR XML PATH('') 
     ) 
    FROM @Location L 
    FOR XML PATH('') 
), 1, 2, '') 
+0

ありがとうございました。私はそれを見ます。私はcte1としてエイリアス化されたレベルを削除することでそれを少し簡略化することができました。とにかく現在は生産中であり、うまく働いているようです(苦情はありません)。もう一度感謝して、私の質問が下投票されなくなったことを嬉しく思います。私はstackoverflow非常に便利だが、強迫を理解することはできませんが、明らかに個人がすぐに外観に反して、私は自分自身で解決して尋ねる両方の時間を過ごしたように見えるかもしれない明確で単純な方法で... – Erg

+0

私は挑戦を理解しています - 私はずっと前に、いくつかの傲慢さを他の人のためにそれを台無しにしないように学んできました。私はあなたの例の詳細レベルを高く評価しました。有用であるかもしれない答えを自由にupvoteしてください;-) –

関連する問題