ugrás a tartalomhoz

MySQL update + join kérdés

tisch.david · 2011. Okt. 6. (Cs), 22.03
Sziasztok!

Meg tudja valaki magyarázni, hogy hogyan működik ez a kód:
UPDATE FELHASZNALO F 
  JOIN RENDELES R ON R.FELHASZNALO_KOD = F.KOD AND R.KOD = 12 
    JOIN RENDELES_TETEL RT ON RT.RENDELES_KOD = R.KOD 
SET F.BONUSZ = F.BONUSZ + RT.BONUSZ
Én azt várnám, hogy a 12-es rendelés tételeinek bónusz pontját fogja jóvá írni a megrendelő felhasználónak. Ennek ellenére mindig csak az első tétel bónuszpontját írja jóvá a többit nem. Miért?

Köszönöm előre is:

Dávid
 
1

szerintem az tortenik, hogy

Tyrael · 2011. Okt. 7. (P), 00.00
szerintem az tortenik, hogy mivel az osszes sorodban azonos a FELHASZNALO tabla oszlopainak az erteke, ezert a mysql csak az elso sorra hajtja vegre az update-et.
egy jol sikerult GROUP BY + SUM megoldas lehet a problemadra.

doksiban nem talaltam se pro se kontra emlitest errol, a bugs.mysql.com-on korulnezve egy ilyet talaltam:
http://bugs.mysql.com/bug.php?id=11495

nem tudtak reprodukalni, de csak azert, mert az ottani updatelendo tablaban nem volt olyan rekord, amihez tobb sor tartozott volna a joinolt tablakban.

sql standardot lehetne meg megnezni, hatha ez ott definialt viselkedes, ha jol emlekszem a mysql a SQL:2003 standardot probalja kovetni.

Tyrael
2

UPDATE helyett először játssz

Hidvégi Gábor · 2011. Okt. 7. (P), 07.48
UPDATE helyett először játssz SELECT-tel, amíg ki nem tudod írni az összes sort.
3

Nem dokumentált/ismert tulajdonság

tisch.david · 2011. Okt. 7. (P), 08.55
Sziasztok!

Köszönöm a válaszokat!
Tyrael:
Igen, valószínűleg ez történhet, bár engem továbbra is meglep, hogy így működik a motor. Miután - Hozzád hasonlóan - én is csak olyan példákat találtam, ahol 1 sorhoz 1 kapcsolt van, végül én is a GROUP BY + SUM párossal oldottam meg a kérdést.

Gábor:
A SELECT sajnos nem segít, mert ha ezt átírod lekérdezéssé, akkor álomszépen hozza a szükséges sorokat, az UPDATE viszont felhasználónként csak egyszer hajtódik végre.

Üdv:

Dávid
4

Furcsa. Mindenesetre azt

Hidvégi Gábor · 2011. Okt. 7. (P), 09.28
Furcsa. Mindenesetre azt javaslom, hogy a JOIN-oknál az ON paramétereit rakd zárójelbe, olvashatóbb így és egyértelműbb.
5

amig igy van tordelve, ahogy,

Tyrael · 2011. Okt. 7. (P), 10.11
amig igy van tordelve, ahogy, addig szerintem igy is tokeletesen olvashato.

Tyrael
6

Szerintem ez így logikus

csla · 2011. Okt. 7. (P), 11.10
Szerintem ez így logikus működés, mert ha nem nézzük, hogy mi van az értékadás jobb oldalán, akkor mi (más, mint a sorrend) alapján döntené el, hogy melyik értéket rendelje a művelet bal oldalához? (Tehát ha pl. F.BONUSZ = RT.BONUSZ lenne, vagy hasonló művelet.) Így egyértelmű, ha összeget akarunk, akkor összeget adjunk értéknek, használjuk a SUM-ot.
7

Ízlések és pofonok

tisch.david · 2011. Okt. 7. (P), 13.16
Szia!

Tudom, hogy ízlések és pofonok különböznek, de számomra azért nem logikus ez, mert ez a JOIN-os lekérdezés, ami az UPDATE belsejében van, több sort adhat vissza minden felhasználóhoz, az UPDATE pedig - várakozásaim szerint - minden visszaadott sorra el kéne, hogy végezze az értékadást. Ez mindaddig így is van, amíg nincs JOIN, vagy van, de 1:1 kapcsolat van a szülő és a gyerek tábla között. Csak akkor viselkedik így, ha 1:n kapcsolat van közöttük.

Ha szerinted ezzel együtt is logikus így, akkor el tudnád magyarázni? Hátha én is megértem.

Üdv:

Dávid
8

az UPDATE pedig -

csla · 2011. Okt. 9. (V), 00.25
az UPDATE pedig - várakozásaim szerint - minden visszaadott sorra el kéne, hogy végezze az értékadást


Hétköznapi szöveges példa, ami talán még jobban szemlélteti. Azt a feladatot kapod, hogy: Pisti zsebpénze legyen egyenlő annyival, amennyit az osztálytársai is kapnak. Megnézed sorban, hogy mennyi zsebpénzt kapnak az osztálytársai, ezek különböző összegek. Mivel más utasítást nem kaptál, nem tudod, mi alapján döntsd el, hogy most akkor mennyi is legyen (inkább a kevesebb, vagy inkább a több), hát - az egyszerűség és a legkevesebb energiaráfordítás okán - azt mondod, akkor legyen annyi, mint azé az osztálytársáé, akiét legelőször nézted meg.

És ha a feladatot úgy határozzuk meg, ahogy te az eredeti értékadást (F.BONUSZ = F.BONUSZ + RT.BONUSZ), akkor így szól: Pisti zsebpénzét emeld meg annyival, amennyit az osztálytársai is kapnak. A nehézség ugyanaz, csak itt tudjuk, hogy mennyi volt Pisti eddigi zsebpénze, de az emelés összegére nézve szintén több lehetőségünk van, lásd az előző példa. És egész biztos, hogy nem úgy járnál el, hogy akkor Pisti zsebpénzét annyiszor növelnéd, ahány osztálytársától megkérdezed, hogy ő mennyit kap.

Tehát a lényeg, hogy egy darab értékadás van csak, mert az egyenlőségjel bal oldalán csak egy sor egy mezője áll (F.BONUSZ), míg a jobb oldalán több sor egy-egy mezője (RT.BONUSZ), még akkor is, ha ez egy SELECT-es kiírásban úgy néz ki, hogy minden sorba odaírja az F.BONUSZ értékét. Ebben az esetben a sorok csak értékadási lehetőségeket jelölnek.