SQL Server에서 하위 쿼리를 사용하여 쿼리 업데이트


83

다음과 같은 간단한 테이블 구조가 있습니다.

테이블 tempData

╔══════════╦═══════╗
║   NAME   ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║    80 ║
║ Ravi     ║    85 ║
║ Sanjay   ║    90 ║
╚══════════╩═══════╝

그리고 이와 같은 tempDataView 와 같은 다른 테이블 이름도 있습니다.

╔══════════╦═══════╗
║   NAME   ║ MARKS ║
╠══════════╬═══════╣
║ Narendra ║       ║
║ Narendra ║       ║
║ Narendra ║       ║
║ Narendra ║       ║
║ Ravi     ║       ║
║ Ravi     ║       ║
║ Sanjay   ║       ║
╚══════════╩═══════╝

나는 테이블 업데이트 할 tempDataView를 설정에 따라, 마크 받는 사람에 따라 tempDataView을 - 이름 에 비해 tempData - 이름

예, 내가 시도한 것을 보여 드리겠습니다. 커서를 사용 하여이 문제를 해결하려고 시도했으며 완벽하게 해결되었지만 하위 쿼리를 사용하여 해결하는 방법을 찾고 있습니다.

여기있어:

Declare @name varchar(50),@marks varchar(50)
Declare @cursorInsert CURSOR
set @cursorInsert = CURSOR FOR
Select name,marks from tempData
OPEN @cursorInsert
FETCH NEXT FROM @cursorInsert
into @name,@marks
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE tempDataView set marks = @marks where name = @name
FETCH NEXT FROM @cursorInsert
INTO @name,@marks
END
CLOSE @cursorInsert
DEALLOCATE @cursorInsert

실제로 Subquery를 사용하여 해결하는 것은 숙제와 같습니다.

답변:


180

UPDATE명령문 에서도 두 테이블을 결합 할 수 있습니다 .

UPDATE  a
SET     a.marks = b.marks
FROM    tempDataView a
        INNER JOIN tempData b
            ON a.Name = b.Name

더 빠른 성능을 위해 두 테이블 모두 INDEX에 on 열 marks을 정의하십시오 .

사용 SUBQUERY

UPDATE  tempDataView 
SET     marks = 
        (
          SELECT marks 
          FROM tempData b 
          WHERE tempDataView.Name = b.Name
        )

1
그 권리. 그러나 하위 쿼리를 사용하여 이것을 수행하는 방법을 제안하십시오.
Narendra Pal

1
와 답을 갱신 subquery,하지만 난 오히려 사용하여 JOIN보다 SUBQUERY.
John Woo

1
왜 하나는 정의해야합니다 INDEXmarks열을? Name기둥 에 있어야하지 않습니까?
lindelof

1
오류가 발생했습니다. 하위 쿼리가 2 개 이상의 값을 반환했습니다. 하위 쿼리가 =,! =, <, <=,>,> = 뒤에 오는 경우 또는 하위 쿼리가 표현식으로 사용되는 경우에는 허용되지 않습니다.
Pradip

1
하위 쿼리 자체를 시도하고 결과가 1 개만 나올 때까지 조정하십시오. 아마 변경 SELECTSELECT TOP 1
vahanpwns

33

방금 배우고 있기 때문에 SELECT 조인을 UPDATE 또는 DELETE 조인으로 변환하는 연습을하는 것이 좋습니다. 먼저 다음 두 테이블을 결합하는 SELECT 문을 생성하는 것이 좋습니다.

SELECT *
FROM    tempDataView a
        INNER JOIN tempData b
            ON a.Name = b.Name

그런 다음 두 개의 테이블 별칭 ab. 이러한 별칭을 사용하면 테이블 a 또는 b를 업데이트하는 UPDATE 문을 쉽게 생성 할 수 있습니다. 테이블 a의 경우 JW에서 제공 한 답변이 있습니다. 을 업데이트하려는 경우 b문은 다음과 같습니다.

UPDATE  b
SET     b.marks = a.marks
FROM    tempDataView a
        INNER JOIN tempData b
            ON a.Name = b.Name

이제 문을 DELETE 문으로 변환하려면 동일한 접근 방식을 사용하십시오. 아래 문 a은 이름으로 일치하는 레코드에 대해서만 (b 그대로 유지) 삭제합니다 .

DELETE a
FROM    tempDataView a
        INNER JOIN tempData b
            ON a.Name = b.Name

JW에서 만든 SQL Fiddle을 플레이 그라운드로 사용할 수 있습니다.


5
배우는 올바른 방법입니다. 공부하는 방법을 보여 주신 +1 감사합니다
Narendra Pal

3

여기 내 샘플에서 업데이트 및 하위 쿼리에 동일한 문제가 있었기 때문에 이에 대한 해결책을 찾습니다.

UPDATE
    A
SET
    A.ValueToChange = B.NewValue
FROM
    (
        Select * From C
    ) B
Where 
    A.Id = B.Id

1
이 답변에 감사드립니다! 다른 사람들이 이것을 읽을 수 있도록이 코드가 문제를 해결하는 이유에 대한 설명을 빠르게 추가 할 수 있습니까?
RedBassett

0

이 스레드의 제목은 업데이트에서 하위 쿼리를 사용할 수있는 방법을 묻습니다. 여기에 그 예가 있습니다.

update [dbName].[dbo].[MyTable] 
set MyColumn = 1 
where 
    (
        select count(*) 
        from [dbName].[dbo].[MyTable] mt2 
        where
            mt2.ID > [dbName].[dbo].[MyTable].ID
            and mt2.Category = [dbName].[dbo].[MyTable].Category
    ) > 0

이것이 어떻게 컴파일되는지 잘 모르겠습니다. count (*)가 무엇을 계산할지 알 수있는 group by가 없습니다.
crthompson

@paqogomez는 레코드가있는 테이블에서 시도해보세요. 예 : EventLog에서 count (*)를 선택하십시오. 여기서 year = 2018
Graham Laight

그래서 당신은 단순히 전체 테이블을 세는 것입니다. 나는 내 반대표를지지합니다. 이것은 질문과 관련이 없습니다 (제목에 관계없이)
crthompson

그것은 당신의 특권입니다. 그러나이 스레드의 제목은 "하위 쿼리를 사용하여 쿼리 업데이트"이며, 제 예제는 분명히 그렇게합니다. fyi "전체 테이블"을 계산하지 않습니다. count (*) 뒤에 "where"절이옵니다. 따라서 "where"조건을 충족하는 행을 계산합니다.
Graham Laight

0

다음 은 몇 가지 예제와 함께 업데이트 작업에 대한 멋진 설명입니다. Postgres 사이트이지만 SQL 쿼리는 다른 DB에서도 유효합니다. 다음 예제는 이해하기 쉽습니다.

-- Update contact names in an accounts table to match the currently assigned salesmen:

UPDATE accounts SET (contact_first_name, contact_last_name) =
    (SELECT first_name, last_name FROM salesmen
     WHERE salesmen.id = accounts.sales_id);

-- A similar result could be accomplished with a join:

UPDATE accounts SET contact_first_name = first_name,
                    contact_last_name = last_name
  FROM salesmen WHERE salesmen.id = accounts.sales_id;

그러나 두 번째 쿼리는 salesmen.id가 고유 키가 아닌 경우 예기치 않은 결과를 제공 할 수있는 반면 첫 번째 쿼리는 일치하는 ID가 여러 개인 경우 오류를 발생시킵니다. 또한 특정 accounts.sales_id 항목과 일치하는 항목이없는 경우 첫 번째 쿼리는 해당 이름 필드를 NULL로 설정하는 반면 두 번째 쿼리는 해당 행을 전혀 업데이트하지 않습니다.

따라서 주어진 예에서 가장 신뢰할 수있는 쿼리는 다음과 같습니다.

UPDATE tempDataView SET (marks) =
    (SELECT marks FROM tempData
     WHERE tempDataView.Name = tempData.Name);

불행히도 첫 번째 양식은 MS SQL 서버에서 작동하지 않습니다.
AntoineL
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.