Aktív témák
-
Taybore
aktív tag
Sziasztok!
Remélem van köztetek valaki, aki perfect MySQL szakértő, mert több táblás kapcsolat lekérdezésre lenne szükségem és nem vagyok túl jártas a laza kapcsolatokban.
Alapszitu:
Van 5 tábla egy fórum motorban (php-s cucc): téma AS T, user AS U, komment AS K, megosztás AS M, látogatás AS L
A dolog úgy működik, hogy a témákat csak azok a userek láthatják (írhatnak kommentet), amik meg van osztva velük. Tehát van egy rekord M-ben U.id és T.id értékekkel. Amikor "belép" egy témába, akkor L-be felíródik a T.id, U.id és a dátum. Természetesen K-ban is van U.id, T.id és dátum.
Nekem egy olyan lekérdezés kéne, amiben kiírja a T.cim, U.nick és count(új kommentek)
Az új kommenteken azt értem (témánként), ahol K.dátum > L.dátum.
Eddig ezt az SQL-t írtam hozzá:SELECT u.nick, t.cim, count(1)
FROM tema t, user u, megosztas m, komment k, temalatogatas l
WHERE m.user_id = u.user_id
AND m.tema_id = t.tema_id
AND l.user_id = u.user_id
AND l.tema_id = t.tema_id
AND k.tema_id = t.tema_id
AND k.datum > l.datum
GROUP BY u.nick, t.cimA probléma az, hogy ha van olyan téma, ami meg van osztva adott userral, de még sose lépett be, akkor nincs témalátogatás rekordja. Ezt kéne valahogy laza kötéssel (LEFT-RIGHT JOIN) megoldani. Az eredmény tehát az kéne hogy legyen, hogy ki, melyik témából hány kommentet nem olvasott még el.
Baromira remélem, hogy érthetően írtam le, és nem hagytam ki semmit.
Előre is köszi a segítséget! -
shev7
veterán
ha join-t akarsz hasznalni, akkor miert nem azt hasznalsz es miert a where-ben kapcsolod ossze a tablakat?
pl
FROM tema t JOIN megosztas m ON t.tema_id = m.tema_id
Ha azt akarod hogy olyan temak is szerepeljenek amikhet nincs megosztas akkor LEFT JOIN. Ha forditva, olyan megosztasok is szerepeljenek amikhez nincs tema akkor RIGHT. Es ajanlatos a tablak osszekapcsoladahoz mindih JOIN-t hasznalni a WHERE feltetelek helyett.
[ Szerkesztve ]
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
Taybore
aktív tag
Azért nem, mert mint írtam, nem tudom hogyan kéne. Ha tudnám, és azt használnám, akkor nem nyitottam volna meg a topicot.
Azt tudom (kismillió helyen leírták), hogy hogyan működik a JOIN, de mindenhol 2 táblára vonatkoztatnak. Nálam (mint láthat) bonyolultabb a helyzet, mivel összekötő táblák is vannak (M és L). Azt nem tudom, hogy melyik táblát (valószínüleg L-t), melyikhez kell milyen JOIN-olni, és milyen sorrendben. Mi kerül az ON részbe és mi marad a WHERE-ben?
Szerk.: Ja és nem olyan táblák kellenek, amikhez nincs megosztás, hanem, amikhez van X usernek megosztása, de nincs látogatás rekordja. (Feltételezhetjük, hogy minden témához van legalább 1 megosztott user, pont aki létrehozta a témát.)[ Szerkesztve ]
-
cucka
addikt
Először is: ez a kérdés miért nem fért el a mysql topikban?
Másodszor: ha kettőnél több táblát join-olsz, akkor azt felfoghatod úgy is, mint ha kettesével végeznéd a join-okat. Tehát az első kettőt összekapcsolod, ennek az eredményét a harmadikkal, ennek az eredményét a negyedikkel, stb.
A vesszővel felsorolt táblanevek gyakorlatilag megfelelnek annak, ha a táblák Déscartes szorzatát vennéd, tehát erősen ellenjavallott a használatuk. Ha például 3, egyenként 200 soros táblát szorzol össze így, akkor az eredménynek 8 millió sora lesz, tehát rossz esetben ennyi sor között fognak keresgélni a where feltételeid. (rossz eset alatt értsd azt, ha a MySQL nem optimalizálja ki a sorrendet. Általában sikerül neki, de bonyolult lekérdezéseknél előfordul, hogy be kell neki segíteni )
-
shev7
veterán
a sorrend teljesen mindegy. Elindulsz egy tablabol, es hozzajoinolod a tobbit. Gyakorlatilag mindig ket tablad van. Az elso join-nal ez egyertelmu. A masodikanal az egyik tablad az elozo lepesben osszejoinolt ket tablad lesz, a masik meg amit eppen hozzajoinolsz. az ON-ba azt irod amit egyebkent a whereben is irnal. A wherebe meg marad a tenyleges feltetel, jelen esetben a datumok osszehasonlitasa...
Az hogy mi kell neked, majd beallitod a join-ok megfelelo left join vagy right joinra cserelesevel:
Pelda harom tablara
FROM tema t JOIN megosztas m ON t.tema_id = m.tema_id
JOIN user u ON u.user_id = m.user_idHa valamire meg akarod engedni, hogy ures legyen, akkor hasznalod a LEFT vagy RIGHT-ot. Ertelem szeruen, ha a JOIN bal oldalan allo halmazbol azokat is meg akarod jeleniteni amihez nincs kapcsolodo elem, akkor LEFT kulonben RIGHT. De elmagyarazni ezt sokkal nehezebb, mint ha leulsz es kiprobalod. Egyszer kell megerteni
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
Taybore
aktív tag
Válasz #4 és #5-re (kb ugyanazt írtátok):
köszi, azt hiszem a logikája így érthető. Ezt az apróságot nem tudtam, amúgy hidd el, próbálkoztam én már mindenféle kombinációval, de sehogy se az jött ki, amit szerettem volna. Ennek a tudásnak a birtokában újra nekiülök próbálkozni
Azért pedig elnézést, hogy nem a nagy MySQL topicba írtam, csak rákerestem a két kifejezésre, és nem talált egyezést, ezért bátorkodtam új témát nyitni. -
-
Taybore
aktív tag
Na nem sikerült célba érnem. A gond szerintem az, hogy kellene az összes U és összes T, de a nem tudom őket összekapcsolni közvetlenül, csak az M-en keresztül, és nem tudom hova kéne a JOIN. Ráadásul meg van még bonyolítva ugye L-el, amiben nincs meg a mind-mind kapcsolat T-re és U-ra.
Azt hiszem valami olyasmit szeretnék, ami ORACLE-ben így nézhet ki:
(a dátumhoz nem tudom pontosan, hogy kellene-e a +)
SELECT u.nick, t.cim, count(1)
FROM tema t, user u, megosztas m, komment k, temalatogatas l
WHERE m.user_id = u.user_id
AND m.tema_id = t.tema_id
AND l.user_id (+) = u.user_id
AND l.tema_id (+) = t.tema_id
AND k.tema_id = t.tema_id
AND k.datum > l.datum (+)
GROUP BY u.nick, t.cimSajna már 3 napja ezzel a problémával küzdök
-
Taybore
aktív tag
Így már kiírja szépen mindegyik témát, mellé mindegyik felhasználót (n*m rekordba), de a count mindenhova 1 egy ad értéknek.
SELECT t.cim, u.nick, count(1)
FROM megosztas m LEFT JOIN temalatogatas l ON m.tema_id = l.tema_id AND m.user_id = l.user_id
LEFT JOIN user u ON u.user_id = m.user_id
LEFT JOIN tema t ON t.tema_id = m.tema_id
LEFT JOIN komment k ON k.user_id = l.user_id AND k.tema_id = l.tema_id
AND k.datum > l.datum
GROUP BY t.cim, u.nick
ORDER BY 1,2Nekem meg ugye az a darabszám kell, ami a user-téma viszonylatban később íródott, mint ahogy a user meglátogatta a témát.
-
Taybore
aktív tag
Asszem sikerült
SELECT u.nick, t.cim, count(k.komment_id) AS darab
FROM (tema t, user u, megosztas m)
LEFT JOIN temalatogatas l ON l.user_id = m.user_id AND l.tema_id = m.tema_id
LEFT JOIN komment k ON k.tema_id = m.tema_id AND IFNULL(l.datum,0) < k.datum
WHERE m.user_id = u.user_id
AND m.tema_id = t.tema_id
GROUP BY u.nick, t.cimEz ránézésre azt adja ki, amit elvártam tőle.
Köszönöm a rávezetést!
Ami még kellett hozzá, az, hogy zárójellel 3 tábla kapcsolatához JOIN.-oltam (ezt nem tudtam), a másik az IFNULL (NVL@ORA) használata a látogatatlan témák megszámolásához.
Most épp örülök -
shev7
veterán
bar meg mindig nem ertem ,hogy a tema usermegosztas harmas miert descartes szorzat. Ha ugyis szursz a megfelelo rekordokre a whereben, miert nem joinolod egybol?
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
Taybore
aktív tag
Nem tudom. Most tanulom a JOIN-t, eddig nem nagyon használtam. Miért, te hogy oldanád meg szépen?
-
shev7
veterán
FROM (tema t, user u, megosztas m)
helyett
FROM tema t JOIN megosztas m on m.tema_id = t.tema_id
JOIN user u ON m.user_id = u.user_idEs igy nem kell a WHERE
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
Taybore
aktív tag
Ez így hatékonyabb megoldás? Mert vannak még további WHERE-ek, csak az egyszerűség kedvéért nem írtam ide. (Pl: ... AND u.allapot = 1 AND u.ertesitest_ker = 1 AND t.allapot = 1, stb...) Ezek nem táblakapcsolathoz tartozó feltételek, hanem az egész SELECT-et szűkítik. Ezeket nem lehet az ON-ba betenni, nem?
-
shev7
veterán
nem, az on-ba csak tablakapcsolathoz valo feltetelt tegyel, a where-t meg hagyd meg amire valo, talalatok szuresere. Szoval igen, azokat oda kell tenni.
Nem azt mondom, hogy ne hasznalj where-t. Nincs azzal semmi baj, csak hasznald arra amire valo, mert ahogy mar korabban mondtuk nem biztos, hogy a db engine mindent ki tud optimalizalni, nem art ha segitesz neki.
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
Taybore
aktív tag
SELECT u.nick, u.email, t.cim, count(k.komment_id) AS darab
FROM tema t JOIN megosztas m ON m.tema_id = t.tema_id
JOIN user u ON m.user_id = u.user_id
LEFT JOIN temalatogatas l ON l.user_id = m.user_id AND l.tema_id = m.tema_id
LEFT JOIN komment k ON k.tema_id = m.tema_id AND IFNULL(l.datum,0) < k.datum
WHERE t.allapot = '1'
AND u.allapot = '1'
AND u.ertesitest_ker = '1'
GROUP BY u.nick, u.email, t.cim
ORDER BY 1,3Így gondoltad? Ez így akkor elvileg hatékonyabb, vagy legalábbis nem bízza a véletlenre a hatékonyságot?
-
shev7
veterán
igen, a legtobb db szoftver kioptimalizalja a lekerdezest. Siman eszreveszi, hogy ha a where-ben olyan feltetel van aminek igazandibol join-ban lenne a helye. De mint mondtuk koran sem tokeletes. Komolyabb lekerdezesnel eltevedhet az optimalizalo. Nem art hozzaszokni a JOIN hasznalatahoz, kesobb jol johet.
''Gee, Brain, what do you want to do tonight?'' ''The same thing we do every night, Pinky: Try to take over the world!''
-
emre33
addikt
Üdv
Alábbi lekérdezést lehet egyszerűbben is elvégezni?
WHERE feltételét el lehet hagyni, valami másik join-al?be_szam táblából azok az értékek kellenének, amik a szamlaell táblába nincsenek meg.
vonalkod ami egyforma.
KöszSELECT *
FROM be_szam
LEFT JOIN szamlaell ON szamlaell.vonalkod=be_szam.vonalkod
WHERE
szamlaell.vonalkod is null
LIMIT 0 , 30ASUS B650E-E, AMD Ryzen 9 7900, CORSAIR 64GB DDR5 6000MHz CL30 KIT CMK64GX5M2B6000Z30, ARCTIC COOLING Liquid Freezer II 360
-
ArchElf
addikt
SELECT *
FROM be_szam
WHERE vonalkod NOT IN (SELECT vonalkod FROM szamlaell)
LIMIT 0 , 30
Gyorsabbnak nem tudom gyorsabb-e, ki kell próbálni...AE
Csinálok egy adag popcornt, és leülök fórumozni --- Ízlések és pofonok - kinek miből jutott --- Az igazi beköpőlégy [http://is.gd/cJvlC2]
Aktív témák
- Playstation 5 lemezes,5 honapos,19 ho garanciával
- MSI H61M-P31/W8 LGA 1155 alaplap
- Teljesen új ASUS ZenBook UX325EA-KG666W (Intel i5 1135G7) laptop eladó (bontatlan+garanciás)
- Új, bontatlan Samsung S24+ 256 GB black
- Dell Latitude E7270, 12,5" HD Kijelző, i5-6300U CPU, 8GB DDR4, 256GB SSD, W10, Számla, Garancia