2012-07-21 21 views
42

Czy ktoś może zobaczyć, co jest nie tak z poniższym zapytaniem?zapytanie o aktualizację mysql z sub-zapytaniem

Gdy uruchomię go uzyskać:

# 1064 - Masz błąd w składni SQL; sprawdzić podręcznika, który odpowiada twojej wersji serwera MySQL dla prawego składnię używać blisko „a gdzie a.CompetitionID = Competition.CompetitionID” at line 8

Update Competition 
Set Competition.NumberOfTeams = 
(
SELECT count(*) as NumberOfTeams 
FROM PicksPoints 
where UserCompetitionID is not NULL 
group by CompetitionID 
) a 
where a.CompetitionID = Competition.CompetitionID 

Odpowiedz

113

Głównym problemem jest to, że zapytanie wewnętrzna nie może być powiązane z twoją klauzulą ​​where na zewnętrznej instrukcji update, ponieważ filtr where dotyczy najpierw tabeli aktualizowanej przed wykonaniem wewnętrznego podkwerendy. Typowym sposobem radzenia sobie z taką sytuacją jest multi-table update.

Update 
    Competition as C 
    inner join (
    select CompetitionId, count(*) as NumberOfTeams 
    from PicksPoints as p 
    where UserCompetitionID is not NULL 
    group by CompetitionID 
) as A on C.CompetitionID = A.CompetitionID 
set C.NumberOfTeams = A.NumberOfTeams 

Demo: http://www.sqlfiddle.com/#!2/a74f3/1

+1

Bardzo dziękuję, że udało się :) Docenić również wyjaśnienie, okrzyki! – user1542043

+0

To wyjaśnienie sprawiło, że była to naprawdę dobra odpowiedź. –

15

Dzięki, nie miałem ideę aktualizacja z INNER JOIN.

W pierwotnym zapytaniu błędem było nazwanie podkwerendy, która musi zwrócić wartość, a zatem nie może być aliasowana.

UPDATE Competition 
SET Competition.NumberOfTeams = 
(SELECT count(*) -- no column alias 
    FROM PicksPoints 
    WHERE UserCompetitionID is not NULL 
    -- put the join condition INSIDE the subquery : 
    AND CompetitionID = Competition.CompetitionID 
    group by CompetitionID 
) -- no table alias 

powinien załatwić sprawę za każdy rekord Konkursu.

aby być zauważonym:

Efekt nie jest dokładnie taka sama jak w zapytaniu proponowanej przez mellamokb, które nie będą aktualizować rekordy konkursowych bez odpowiednich PickPoints.

Od SELECT id, COUNT(*) GROUP BY id będzie liczyć tylko na istniejących wartości identyfikatorów,

natomiast SELECT COUNT(*) zawsze zwróci wartość jest 0, jeśli nie wybrano żadnych rekordów.

To może, ale nie musi, stanowić problem dla Ciebie.

0 świadomy wersja zapytania mellamokb byłoby:

Update Competition as C 
LEFT join (
    select CompetitionId, count(*) as NumberOfTeams 
    from PicksPoints as p 
    where UserCompetitionID is not NULL 
    group by CompetitionID 
) as A on C.CompetitionID = A.CompetitionID 
set C.NumberOfTeams = IFNULL(A.NumberOfTeams, 0) 

Innymi słowy, jeśli nie zostaną znalezione żadne odpowiadające PickPoints, zestaw Competition.NumberOfTeams do zera.

4

Dla niecierpliwych:

UPDATE target AS t 
INNER JOIN (
    SELECT s.id, COUNT(*) AS count 
    FROM source_grouped AS s 
    -- WHERE s.custom_condition IS (true) 
    GROUP BY s.id 
) AS aggregate ON aggregate.id = target.id 
SET t.count = aggregate.count 

To @mellamokb „s odpowiedź, jak wyżej, sprowadza się do max.

Powiązane problemy