更新が必要な大きなテーブルがあります。私はWDの値に一致するように、ヌルWD値を持っているそれらのレコードのWDの列を更新する必要が再帰SQLクエリの最適化
CREATE TABLE T
([Errors] varchar(4), [MRN] int, [EPI] varchar(13), [WD] varchar(4));
INSERT INTO T
([Errors], [MRN], [EPI], [WD])
VALUES
(NULL, 107, 'IP00001070001', 'AMUM'),
(NULL, 107, 'IP00001070001', 'AMUM'),
(NULL, 107, 'IP00001070001', 'KNAP'),
(NULL, 107, 'IP00001070002', 'KNAP'),
(NULL, 107, 'IP00001070002', 'KNAP'),
(NULL, 107, 'IP00001070002', 'KNAP'),
(NULL, 107, 'IP00001070002', 'KNAP'),
(NULL, 381, 'IP00003810001', 'EAUS'),
(NULL, 381, 'IP00003810001', 'EAUS'),
(NULL, 381, 'IP00003810003', 'DOCK'),
(NULL, 381, 'IP00003810003', NULL),
(NULL, 45, 'IP00000450001', 'ASES'),
('__', 45, 'IP00000450002', NULL),
('__', 381, 'IP00003810002', NULL);
...次の例(しかし、私のは本当に大規模な1M +行と複数の列である)によって定義されます[MRN]と[EPI]によって発注された場合の最初のエントリ。たとえば、必要な出力は次のようになります。
Errors MRN EPI WD
NULL 107 IP00001070001 AMUM
NULL 107 IP00001070001 AMUM
NULL 107 IP00001070001 KNAP
NULL 107 IP00001070002 KNAP
NULL 107 IP00001070002 KNAP
NULL 107 IP00001070002 KNAP
NULL 107 IP00001070002 KNAP
NULL 381 IP00003810001 EAUS
NULL 381 IP00003810001 EAUS
NULL 381 IP00003810003 EAUS
NULL 381 IP00003810003 EAUS
NULL 45 IP00000450001 ASES
__ 381 IP00003810003 EAUS
__ 45 IP00000450002 ASES
__ 381 IP00003810002 EAUS
編集したレコードを下部に表示します。これは私が欲しいものです。しかし、このメソッドはSLLLLOOOOWWWです...非常に遅く、正当な理由で、私は全体のセットをループしています。私の質問はすでにターゲットテーブルのインデックスを作成しています:
- このクエリ/操作を最適化するにはどうすればよいですか?
- ここでも再帰が必要ですか?お時間を
IF EXISTS ( SELECT name FROM sys.tables WHERE name = N'T') DROP TABLE [T] GO CREATE TABLE T ([Errors] varchar(4), [MRN] int, [EPI] varchar(13), [WD] varchar(4)); INSERT INTO T ([Errors], [MRN], [EPI], [WD]) VALUES (NULL, 107, 'IP00001070001', 'AMUM'), (NULL, 107, 'IP00001070001', 'AMUM'), (NULL, 107, 'IP00001070001', 'KNAP'), (NULL, 107, 'IP00001070002', 'KNAP'), (NULL, 107, 'IP00001070002', 'KNAP'), (NULL, 107, 'IP00001070002', 'KNAP'), (NULL, 107, 'IP00001070002', 'KNAP'), (NULL, 381, 'IP00003810001', 'EAUS'), (NULL, 381, 'IP00003810001', 'EAUS'), (NULL, 381, 'IP00003810003', 'DOCK'), (NULL, 381, 'IP00003810003', 'DOCK'), (NULL, 45, 'IP00000450001', 'ASES'), ('__', 381, 'IP00003810003', NULL), ('__', 45, 'IP00000450002', NULL), ('__', 381, 'IP00003810002', NULL); IF EXISTS (SELECT * FROM sys.indexes WHERE name='idxEETEST' AND object_id = OBJECT_ID('T')) DROP INDEX [idxEETEST] ON [T]; GO CREATE NONCLUSTERED INDEX [idxEpiIPWardLoad] ON [T] ([MRN], [EPI]) GO DECLARE @sql NVARCHAR(MAX) DECLARE @mrn INT DECLARE @epi NVARCHAR(16) DECLARE @get_rec CURSOR SET @get_rec = CURSOR FOR SELECT MRN, EPI FROM T WHERE Errors IS NOT NULL OPEN @get_rec FETCH NEXT FROM @get_rec INTO @mrn, @epi WHILE @@FETCH_STATUS = 0 BEGIN SET @sql = 'DECLARE @wd VARCHAR(4); ' + 'SELECT TOP 1 @wd = WD ' + 'FROM T ' + 'WHERE MRN = ' + Convert(VARCHAR, @mrn) + ';' + 'UPDATE T ' + 'SET WD = @wd ' + 'WHERE MRN = ' + Convert(VARCHAR, @mrn) + ' AND EPI = ''' + @epi + '''' EXEC(@sql); FETCH NEXT FROM @get_rec INTO @mrn, @epi END CLOSE @get_rec DEALLOCATE @get_rec GO IF EXISTS (SELECT * FROM sys.indexes WHERE name='idxEETEST' AND object_id = OBJECT_ID('T')) DROP INDEX [idxEETEST] ON [T]; GO
ありがとう:
はここで助けて喜んでいる人を支援するために設定し、全テストクエリです。
なぜ動的SQLでループを使用して更新していますか?これは、動的SQLまたはループのない単一の更新文として書き直すことができます。 –
私は地獄のように錆びていて、再帰せずに同じテーブルを更新するバッチの最初のレコードをどのように得ることができるか見て苦労していたからです。どんな助けも大いに受け取ります。 – MoonKnight
私はあなたがここで成し遂げようとしていることの論理には全く従っていません。ビジネスルールを説明できますか? –