web-dev-qa-db-ja.com

MySQL / SQL:更新されたテーブル自体からの相関サブクエリで更新します

例を使って説明しようとする一般的な質問があります。

「id」、「name」、「category」、「appearances」、「ratio」のフィールドを持つテーブルがあるとします。

私にはいくつかのアイテムがあり、それぞれが1つのカテゴリに関連していて、何度も「表示」されるという考え方です。比率フィールドには、カテゴリ内のアイテムの出現総数に対する各アイテムの出現の割合を含める必要があります。

擬似コードで必要なのは次のとおりです。

  • カテゴリごと
    それに関連するアイテムの出現の合計を見つけます。たとえば、(select sum("appearances") from table group by category)で実行できます。

  • アイテムごと
    比率の値を、アイテムの外観を上記のカテゴリで見つかった合計で割った値として設定します

今、私は単一の更新クエリでこれを達成しようとしていますが、それを行うことができないようです。私がすべきだと思ったことは次のとおりです。

update Table T    
set T.ratio = T.appearances /   
(    
select sum(S.appearances)    
from Table S    
where S.id = T.id    
)

しかし、MySQLは更新列のエイリアスTを受け入れず、これを実現する他の方法は見つかりませんでした。

何か案は?

19
Roee Adler

私が受け取った2つの答え(どれも完全ではなかったので、私は自分で書いた)に続いて、私が最終的にしたことは次のとおりです。

UPDATE Table AS target
INNER JOIN 
(
select category, appearances_sum
from Table T inner join (
    select category as cat, sum(appearances) as appearances_sum
    from Table
    group by cat
) as agg
where T.category  = agg.cat
group by category
) as source
ON target.category = source.category
SET target.probability = target.appearances / source.appearances_sum 

それは非常に迅速に動作します。相関サブクエリも試してみましたが、はるかに遅い(桁違い)ので、結合に固執しています。

46
Roee Adler

UPDATEの直後に結合を使用します: リファレンスマニュアル– 13.2.11 UPDATE構文

したがって、UPDATE table1 inner join table2 on .... set table1.foo = value where table2.bla = someothervalue

このような場合は、必ずマニュアルをご覧ください。 MySqlには適切なリファレンスマニュアルがあるので、正しい構文を取得するのはそれほど難しいことではありません;)

6
Frans Bouma

これはmssqlで行われる方法です。mysqlは同じか類似していると思います。

create table T (id int, ratio float, appearances int)
insert T values (1, null, 2)
insert T values (1, null, 3)

update T
set ratio = cast(appearances as float)/ agg.appearancesSum
from T join (
    select id, sum(appearances) as appearancesSum
    from T
    group by id
) as agg on t.id = agg.id
2
ahains