SQLServerのサブクエリを使用してクエリを更新する


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

実際、サブクエリを使用してそれを解決するのは宿題のようなものです。

回答:


180

UPDATEステートメントでも両方のテーブルを結合できます。

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

パフォーマンスを向上させるには、両方のテーブルにINDEXon列marksを定義します。

を使用して SUBQUERY

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

1
それはそうです。ただし、サブクエリを使用してこれを行う方法を提案してください。
ナレンドラパル2013年

1
で答えを更新しましたsubqueryが、私はではなくを使用しJOINていSUBQUERYます。
ジョンウー

1
なぜ1は定義すべきINDEXmarks列?それはName列にあるべきではありませんか?
リンデロフ2015年

1
エラーが発生しました:サブクエリが複数の値を返しました。サブクエリが=、!=、<、<=、>、> =の後に続く場合、またはサブクエリが式として使用される場合、これは許可されません。
Pradip 2016年

1
サブクエリを単独で試して、結果が1つだけになるまで調整します。おそらく次のように変更SELECTしますSELECT TOP 1
vahanpwns 2016

33

学習しているだけなので、SELECT結合をUPDATEまたはDELETE結合に変換する練習をすることをお勧めします。まず、次の2つのテーブルを結合するSELECTステートメントを生成することをお勧めします。

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

次に、2つのテーブルエイリアスaとが存在することに注意してくださいb。これらのエイリアスを使用すると、テーブル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フィドルを遊び場として利用できます


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(*)が何をカウントするかを知るためのgroupbyはありません。
crthompson 2018

@paqogomezは、レコードが含まれているテーブルで試してみてください。例えば。EventLogからcount(*)を選択します。ここで、year = 2018
Graham Laight

したがって、単にテーブル全体を数えているだけです。私は反対票を支持します、これは質問とは何の関係もありません(タイトルに関係なく)
crthompson 2018

それはあなたの特権ですが、このスレッドのタイトルは「サブクエリを使用してクエリを更新する」であり、私の例はそれを正確に実行します。fyi「テーブル全体」をカウントしていません-count(*)の後に「where」句が続きます-したがって、「where」条件を満たす行をカウントしています。
GrahamLaight18年

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が一意のキーでない場合、2番目のクエリで予期しない結果が生じる可能性がありますが、最初のクエリでは、IDが複数一致する場合にエラーが発生することが保証されています。また、特定のaccounts.sales_idエントリに一致するものがない場合、最初のクエリは対応する名前フィールドをNULLに設定しますが、2番目のクエリはその行をまったく更新しません。

したがって、与えられた例では、最も信頼できるクエリは次のようになります。

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

残念ながら、最初の形式はMSSQLサーバーでは機能しません。
AntoineL
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.