私は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
は、あなたのテーブルには、サンプル・データとどのように見えるかの例を追加することができますし、何を使用すると、現在のサンプルデータから取得され、そしてどのようなあなたの代わりに取得しようとしている結果結果? –
親から値をコピーするように各行を更新するか、ルート(祖先)行の値を階層全体に押し込むかしますか?最初のケースでは、再帰的なCTEはまったく必要なく、2番目の場合は、ルート値を引き継ぐために再帰的なCTEの結果に列を追加する必要があります。 –
David - はい、親からサンプルを含む各行を更新したい(シェルフ/ラック/ボックスの行を更新する必要はなく、階層を確立するためだけである)。したがって、サンプルAでは、シェルフ/ラック/ボックスの値が、対応するシェルフ/ラック/ボックスの行の階層内の値と一致するようにします。それは理にかなっていますか?私は、UNION ALL - SELECT文のすべての列を列挙すると、必要なすべてのフィールドが下に引かれたと考えました。 – Selene