1

私はSQLの初心者で、各行の複数の列を階層情報で更新するために、私は多くの例をオンラインで読んだことがありますが、私が必要とするものを正確に記述していないので、誰かが私を助けてくれることを望みます。CTEを使用してテーブル内の複数の列を更新し、テーブル内のすべての行のループを更新します

シェルフが最高レベルで、ボックスが最も低く、ボックスの下にサンプルがあるシェルフ - >ラック - ボックスの階層に保存された学習サンプルの表があります。シェルフ、ラック、ボックスも別の行としてこのテーブルにあります。すべてのアイテムには、それらを識別するための「名前」というフィールドがあります。それらはすべてIDとparent_IDによって接続されています。管理構造のようなもの。

サンプルの各行のすべてのレベル値を設定する必要があります。これは、私がオンラインで見つけたマネージャ/従業員の例よりも複雑です。単に見つけた例のように、単純にSELECTを実行するのではなく、CTEによって返された値を格納する必要があります。

すべての行でCTEを実行するには、WHILEループでCTE全体を入れ子にしてみましたが、すべての行ではなく単一の値でループします。

以下は、現在、1つのサンプル値の階層を返すために働いているコードです。 「tempspec」サンプルテーブルです:

DECLARE @TID float; 
SET @TID = 39059; 
WITH cte AS 
(
    SELECT ID, 
    Parent_Id, 
    Name, 
    Study_ID, 
      Loc_Box, 
      Loc_Shelf, 
      Loc_Rack, 
    Loc_Type 
    FROM tempspec 
    WHERE ID = @TID and Study_ID = 'XXX' 
    UNION all 
    SELECT tempspec.Id, 
      tempspec.Parent_Id, 
      tempspec.Name, 
    tempspec.Study_ID, 
      tempspec.Loc_Box, 
      tempspec.Loc_Shelf, 
      tempspec.Loc_Rack, 
    tempspec.Loc_Type 
    FROM tempspec 
    JOIN cte on tempspec.Id = cte.Parent_Id 
) 
SELECT E1.name, E1.ID, E1.Parent_ID,E1.Loc_Type,ISNULL(E2.name,'TOP') 
FROM cte E1 
LEFT JOIN cte E2 
ON E1.parent_id = E2.ID; 

しかし、私はUPDATEとSELECTを交換しようとした場合、それが実行され、テーブル内のすべての行が更新されていると言うが、何も保存されていない:

UPDATE E1 
SET E1.Loc_Box = E2.Loc_Box, 
E1.Loc_Rack = E2.Loc_Rack, 
E1.Loc_Shelf = E2.Loc_Shelf 
FROM tempspec E1 
LEFT JOIN cte E2 
ON E1.parent_id = E2.ID; 

そして、このWHILEループでCTEをネストしようとすると( 'P'はサンプル行を示しているので、ツリーをトラバースするだけです)、IDを@TIDに割り当てることはできません。それが永遠にループする他の方法を試しました:

WHILE EXISTS(SELECT * FROM tempspec WHERE Loc_Type = 'P') 
BEGIN 
SET @TID = ID; 

私は何が間違っていますか?私は様々なフォーマットを試しましたが、何も動作していないようです。あなたの助けを前もってありがとう!

以下は、要求されたテストデータです。私はサンプルのため、親行から名前値(タイプ=「P」)とシェルフ、ラック、およびボックスを移入したい:1つのサンプルについて

DROP TABLE dbo.TEST_DATA; 
CREATE TABLE dbo.TEST_DATA (int ID, int Parent_Id,varchar(30) Name, varchar(10) Type,varchar(30) Shelf,varchar(30) Rack,varchar(30) Box) 
INSERT INTO TEST_DATA (39702, 1664, 0228MBDNAERA1, 'P','','',''); 
INSERT INTO TEST_DATA (39703, 1664, 0230MBDNAERA1, 'P','','',''); 
INSERT INTO TEST_DATA (39704, 1664, 0231MBDNAERA1, 'P','','',''); 
INSERT INTO TEST_DATA (39726, 1744, 0228MBDNAERA2, 'P','','',''); 
INSERT INTO TEST_DATA (39727, 1744, 0230MBDNAERA2, 'P','','',''); 
INSERT INTO TEST_DATA (39728, 1744, 0231MBDNAERA2, 'P','','',''); 
INSERT INTO TEST_DATA (39764, 1752, 0228MBDNAERA3, 'P','','',''); 
INSERT INTO TEST_DATA (39766, 1752, 0230MBDNAERA3, 'P','','',''); 
INSERT INTO TEST_DATA (39768, 1752, 0231MBDNAERA3, 'P','','',''); 
INSERT INTO TEST_DATA (1744, 1652, MBDNAERA2 - 3, 'B','','',''); 
INSERT INTO TEST_DATA (1752, 1732, MBDNAERA3 - 3, 'B','','',''); 
INSERT INTO TEST_DATA (1664, 1652, MBDNAERA1 - 3, 'B','','',''); 
INSERT INTO TEST_DATA (1732, 1617, Rack R, 'R','','',''); 
INSERT INTO TEST_DATA (1652, 1617, Rack Q, 'R','','',''); 
INSERT INTO TEST_DATA (1617, 2, Shelf 4, 'S','','',''); 
INSERT INTO TEST_DATA (2, NULL, Freezer, 'F','','',''); 

例のデータ階層と結果の行は、私がしようとしています(悪いフォーマットについて申し訳ありません)を取得する:

ID  Parent_Id Name   Type Shelf Rack Box 
39702 1664 0228MBDNAERA1 'P'   
1664 1652 MBDNAERA1 - 3 'B'   
1652 1617 Rack Q   'R'   
1617 2 Shelf 4   'S'   
2   NULL Freezer   'F'   

ID  Parent_Id Name   Type Shelf Rack Box 
39702 1664 0228MBDNAERA1 'P' Shelf 4 Rack Q MBDNAERA1 - 3 
+1

は、あなたのテーブルには、サンプル・データとどのように見えるかの例を追加することができますし、何を使用すると、現在のサンプルデータから取得され、そしてどのようなあなたの代わりに取得しようとしている結果結果? –

+1

親から値をコピーするように各行を更新するか、ルート(祖先)行の値を階層全体に押し込むかしますか?最初のケースでは、再帰的なCTEはまったく必要なく、2番目の場合は、ルート値を引き継ぐために再帰的なCTEの結果に列を追加する必要があります。 –

+0

David - はい、親からサンプルを含む各行を更新したい(シェルフ/ラック/ボックスの行を更新する必要はなく、階層を確立するためだけである)。したがって、サンプルAでは、シェルフ/ラック/ボックスの値が、対応するシェルフ/ラック/ボックスの行の階層内の値と一致するようにします。それは理にかなっていますか?私は、UNION ALL - SELECT文のすべての列を列挙すると、必要なすべてのフィールドが下に引かれたと考えました。 – Selene

答えて

0

はそれを試してみてください。

DECLARE @TEST_DATA as TABLE (ID int , Parent_Id int ,Name varchar(30) , Type varchar(10) ) 
INSERT @TEST_DATA VALUES (39702, 1664, '0228MBDNAERA1', 'P'); 
INSERT @TEST_DATA VALUES (39703, 1664, '0230MBDNAERA1', 'P'); 
INSERT @TEST_DATA VALUES (39704, 1664, '0231MBDNAERA1', 'P'); 
INSERT @TEST_DATA VALUES (39726, 1744, '0228MBDNAERA2', 'P'); 
INSERT @TEST_DATA VALUES (39727, 1744, '0230MBDNAERA2', 'P'); 
INSERT @TEST_DATA VALUES (39728, 1744, '0231MBDNAERA2', 'P'); 
INSERT @TEST_DATA VALUES (39764, 1752, '0228MBDNAERA3', 'P'); 
INSERT @TEST_DATA VALUES (39766, 1752, '0230MBDNAERA3', 'P'); 
INSERT @TEST_DATA VALUES (39768, 1752, '0231MBDNAERA3', 'P'); 
INSERT @TEST_DATA VALUES (1744, 1652, 'MBDNAERA2 - 3', 'B'); 
INSERT @TEST_DATA VALUES (1752, 1732, 'MBDNAERA3 - 3', 'B'); 
INSERT @TEST_DATA VALUES (1664, 1652, 'MBDNAERA1 - 3', 'B'); 
INSERT @TEST_DATA VALUES (1732, 1617, 'Rack R', 'R'); 
INSERT @TEST_DATA VALUES (1652, 1617, 'Rack Q', 'R'); 
INSERT @TEST_DATA VALUES (1617, 2, 'Shelf 4', 'S'); 
INSERT @TEST_DATA VALUES (2, NULL, 'Freezer', 'F'); 

-- SELECT 
;with 
cte_product as (
Select * from @TEST_DATA where Type = 'P'), 
cte_box as (
Select * from @TEST_DATA where Type = 'B'), 
cte_shelf as (
Select * from @TEST_DATA where Type = 'S'), 
cte_rack as (
Select * from @TEST_DATA where Type = 'R') 
Select * from 
cte_product p 
left join cte_box b 
on 
p.Parent_Id = b.ID 
inner join cte_rack r 
on 
b.Parent_Id = r.ID 
inner join cte_shelf s 
on 
r.Parent_Id = s.ID 

結果

ID   Parent_Id Name       Type  ID   Parent_Id Name       Type  ID   Parent_Id Name       Type  ID   Parent_Id Name       Type 
----------- ----------- ------------------------------ ---------- ----------- ----------- ------------------------------ ---------- ----------- ----------- ------------------------------ ---------- ----------- ----------- ------------------------------ ---------- 
39726  1744  0228MBDNAERA2     P   1744  1652  MBDNAERA2 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 
39727  1744  0230MBDNAERA2     P   1744  1652  MBDNAERA2 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 
39728  1744  0231MBDNAERA2     P   1744  1652  MBDNAERA2 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 
39764  1752  0228MBDNAERA3     P   1752  1732  MBDNAERA3 - 3     B   1732  1617  Rack R       R   1617  2   Shelf 4      S 
39766  1752  0230MBDNAERA3     P   1752  1732  MBDNAERA3 - 3     B   1732  1617  Rack R       R   1617  2   Shelf 4      S 
39768  1752  0231MBDNAERA3     P   1752  1732  MBDNAERA3 - 3     B   1732  1617  Rack R       R   1617  2   Shelf 4      S 
39702  1664  0228MBDNAERA1     P   1664  1652  MBDNAERA1 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 
39703  1664  0230MBDNAERA1     P   1664  1652  MBDNAERA1 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 
39704  1664  0231MBDNAERA1     P   1664  1652  MBDNAERA1 - 3     B   1652  1617  Rack Q       R   1617  2   Shelf 4      S 

--UPDATE TABLE 

;with 
cte_product as (
Select * from @TEST_DATA where Type = 'P'), 
cte_box as (
Select * from @TEST_DATA where Type = 'B'), 
cte_shelf as (
Select * from @TEST_DATA where Type = 'S'), 
cte_rack as (
Select * from @TEST_DATA where Type = 'R') 
UPDATE D 
SET 
    Shelf = S.name 
    ,Rack = r.Name 
    ,Box = b.Name 
FROM 
    @TEST_DATA d 
     Inner join 
     cte_product p 
     left join cte_box b 
     on 
     p.Parent_Id = b.ID 
     inner join cte_rack r 
     on 
     b.Parent_Id = r.ID 
     inner join cte_shelf s 
     on 
     r.Parent_Id = s.ID 
On 
    d.ID = p.ID 


select * from @TEST_DATA 

結果は

ID   Parent_Id Name       Type  Shelf       Rack       Box 
----------- ----------- ------------------------------ ---------- ------------------------------ ------------------------------ ------------------------------ 
39702  1664  0228MBDNAERA1     P   Shelf 4      Rack Q       MBDNAERA1 - 3 
39703  1664  0230MBDNAERA1     P   Shelf 4      Rack Q       MBDNAERA1 - 3 
39704  1664  0231MBDNAERA1     P   Shelf 4      Rack Q       MBDNAERA1 - 3 
39726  1744  0228MBDNAERA2     P   Shelf 4      Rack Q       MBDNAERA2 - 3 
39727  1744  0230MBDNAERA2     P   Shelf 4      Rack Q       MBDNAERA2 - 3 
39728  1744  0231MBDNAERA2     P   Shelf 4      Rack Q       MBDNAERA2 - 3 
39764  1752  0228MBDNAERA3     P   Shelf 4      Rack R       MBDNAERA3 - 3 
39766  1752  0230MBDNAERA3     P   Shelf 4      Rack R       MBDNAERA3 - 3 
39768  1752  0231MBDNAERA3     P   Shelf 4      Rack R       MBDNAERA3 - 3 
1744  1652  MBDNAERA2 - 3     B                   
1752  1732  MBDNAERA3 - 3     B                   
1664  1652  MBDNAERA1 - 3     B                   
1732  1617  Rack R       R                   
1652  1617  Rack Q       R                   
1617  2   Shelf 4      S                   
2   NULL  Freezer      F                   
+0

私はCTEの後に1つのUPDATEを実行しようとしています。その特定のサンプル行のシェルフ、ラック、ボックスの値を更新します。これは可能ですか? – Selene

+0

OUTPUTは、Loc_ *列に何も保存されていないことを示します。 – Selene

+0

IDについて異なる調査をしていない場合は、期待どおりの結果です。 –

関連する問題