2009-05-08 14 views
19

Mam ogólne pytanie, które postaram się wyjaśnić za pomocą przykładu.MySQL/SQL: Aktualizacja ze skorelowanym podzapytaniem z zaktualizowanej samej tabeli

Say mam tabeli z polami: „id”, „Kategoria” „name”, „występach” i „stosunek”

Chodzi o to, że mam kilka elementów, każdy związany z pojedynczym kategoria i "pojawia się" kilka razy. Pole wskaźnika powinno uwzględniać procent wyświetleń każdej pozycji z całkowitej liczby wystąpień pozycji w kategorii.

W pseudo-kodu, co potrzebne jest następujące:

  • Dla każdej kategorii
    znaleźć całkowitą sumę występach dla elementów z nią związanych. Na przykład może to być zrobione z (select sum("appearances") from table group by category)

  • dla każdej pozycji
    ustawić wartość współczynnika jak występy elementu, podzielony przez sumę ustalonych dla kategorii powyżej

Teraz jestem próbuje to osiągnąć za pomocą pojedynczego zapytania o aktualizację, ale nie może tego zrobić. Co pomyślałem, że powinienem zrobić to:

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

Ale MySQL nie akceptuje alias T w kolumnie aktualizacji, a nie mogę znaleźć inne sposoby osiągnięcia tego celu.

Wszelkie pomysły?

Odpowiedz

45

Po otrzymaniu dwóch odpowiedzi (z których żadna nie była kompletna, więc napisałem własną), co ostatecznie zrobiłem w następujący sposób:

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 

Działa bardzo szybko. Próbowałem również z skorelowanym podzapytaniem, ale było ono znacznie wolniejsze (rzędy wielkości), więc trzymam się złączenia.

+0

Proszę o oznaczenie odpowiedzi jako odpowiedzi, więc to pytanie zostanie usunięte z listy pytań bez odpowiedzi :) –

+1

@Frans: Musiałem czekać 48 godzin, zanim mogłem to zrobić, zasady przepełnienia stosu :) –

+0

Nice. Dziękujemy za poświęcenie czasu, aby podać pełny przykład! – Ben

3

Jak to jest zrobione w MSSQL, myślę, że mysql jest taka sama lub podobna:

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 
+0

Niestety, to nie działa w MySQL. Nie głosuję w dół, ponieważ jestem pewien, że działa na mssql ... –

6

Zastosowanie łączy zaraz po UPDATE: Reference Manual – 13.2.11 UPDATE Syntax

tak UPDATE tabela1 wewnętrzna przyłączyć Table2 dalej. ... zestaw table1.foo = wartość gdzie table2.bla = someothervalue

Przy takich rzeczach zawsze patrz w instrukcji obsługi. MySql ma odpowiednią instrukcję obsługi, więc nie powinno być tak trudno uzyskać poprawną składnię;)

+0

Dzięki, spróbuję jak najszybciej. A tak na marginesie - zrobiłem RTFM i wypróbowałem wszystko, co miało sens, zanim napisałem pytanie :) –

+0

dzięki, ręczny wpis wyjaśnił mi rozwiązanie.pozytywny dla ciebie także –

Powiązane problemy