MySQL / SQL: обновление с помощью коррелированного подзапроса из самой обновленной таблицы - PullRequest
19 голосов
/ 08 мая 2009

У меня есть общий вопрос, который я попытаюсь объяснить на примере.

Допустим, у меня есть таблица с полями: "id", "name", "category", "внешний вид" и "ratio"

Идея состоит в том, что у меня есть несколько предметов, каждый из которых относится к одной категории и "появляется" несколько раз. Поле отношения должно включать процентное количество появлений каждого элемента от общего числа появлений элементов в категории.

В псевдокоде мне нужно следующее:

  • Для каждой категории
    найти общую сумму появлений для предметов, связанных с ним. Например, это можно сделать с помощью (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 в столбце обновления, и я не нашел других способов добиться этого.

Есть идеи?

Ответы [ 3 ]

46 голосов
/ 10 мая 2009

Следуя двум полученным мной ответам (ни один из которых не был законченным, поэтому я написал свой собственный), я в итоге сделал следующее:

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 

Работает очень быстро. Я также пытался с коррелированным подзапросом, но это было намного медленнее (порядки величины), поэтому я придерживаюсь соединения.

6 голосов
/ 09 мая 2009

Использовать соединения сразу после ОБНОВЛЕНИЯ: Справочное руководство - 13.2.11 ОБНОВЛЕНИЕ Синтаксис

так ОБНОВЛЕНИЕ table1 внутреннее соединение table2 на .... установить table1.foo = значение где table2.bla = someothervalue

С такими вещами всегда смотрите руководство. MySql имеет правильное справочное руководство, поэтому не так уж сложно найти правильный синтаксис;)

2 голосов
/ 08 мая 2009

Вот как это делается в 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
...