업데이트해야 할 큰 테이블이 있습니다. 재귀 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);
내가의 WD의 값과 일치하는 경우는 null WD의 값이 레코드의 WD 열을 업데이트해야합니다 ... 다음의 예에 의해 정의 된 (그러나 광산은 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
나는 당신이 여기에서 성취하려고하는 논리를 따르지 않는다. 비즈니스 규칙을 설명 할 수 있습니까? –