Topic: duomenys iš dviejų lentelių su join

situacija tokia:
yra dvi lentelės:
1. komandos
id | name | city | ...
2. rungtyn4s
id | home_team_id | guest_team_id | result | date | ...
kaip panaudojus vieną užklausą, ištrukt iš pirmos lentelės dviejų komandų pavadinimus, kurie saugomi antroj lentelėj kaip 'home_team_id' ir 'guest_team_id', bei is antros lentelės kitus duomenis (rezultatą, datą...)? jei tai išvis įmanoma.
aš bandžiau taip:
"SELECT time_game.result AS result, time_game.place AS place, commands.name AS home, commands.name AS guest FROM time_game LEFT JOIN commands ON commands.id=time_game.ome_team_id AND commands.id=time_game.guest_team_id WHERE time_game.date>'$date_begin' AND time_game.date<'$date_end' LIMIT 1"
mysql_error'as klaidos nemeta, bet ir negaunu norimo reultato, gaunu tik rezultatą, o komandų pavadinimų ne.

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

įmanoma, beveik teisingai darei, tik loginių klaidų palikai:

SELECT time_game.result AS result,
    time_game.place AS place,
    home.name AS home,
    guest.name AS guest
FROM time_game
    INNER JOIN commands AS home ON time_game.home_team_id = home.id
    INNER JOIN commands AS guest ON time_game.guest_team_id = quest.id
WHERE time_game.date > '$date_begin'
    AND time_game.date < '$date_end'

Atkreipiu dėmesį, kad time_game lentelė jungiama su commands lentele du kartus (abiem atvejais priskiriami skirtingi pavadinimai "home" ir "guest").

Re: duomenys iš dviejų lentelių su join

aišku, ačiū labai.

Su sąlyga, kad šūdo nebus...

4 (edited by Ramex 2008-05-23 10:57:20)

Re: duomenys iš dviejų lentelių su join

dar klausimėlis prie to pačio:
ar egzistuoja kokois nors ribos optimalumo prasme, join'inant lenteles? koks maksimalus apjungiamų lentelių skaičius yra optimalus, jei pvz yra viena pagrindinė lentelė, ir kelios šalutinės kur traukiame viso labo tik po vieną reikšmę su paprastu palyginimu?

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

Dėl "optimalumo" tai reikia žinoti, ką konkrečiu atveju tas žodis reiškia.

Kas dėl apribojimų tai visada egzistuoja visokie fiziniai apribojimai, tik jie yra pakankamai dideli, kad juos taip paprastai pasiektum.

Faktas, kad kuo didesnis JOIN'ų kiekis tuo viskas lėčiau dirba... bet pliusas tame, kad gali sau leisti turėti aukštesnės normalinės formos duomenis.

Bendru atveju reikia išsikelti tikslą, vieni tarkim siekia greičio, kiti patogumo, kiti duomenų vientisumo ir pan. Ir pagal tai, įvertinant visą "biznio logiką" projektuoja duomenų schemas.

6 (edited by Ramex 2008-05-23 12:37:39)

Re: duomenys iš dviejų lentelių su join

na aš panašiai viską ir suprantu, bet tik nežinau kaip kiekvienas JOIN'as veikia užklausos greitį. na duosiu konkretų pvz:
4 lentelės

#1 'details'
id | time | date | country_id | cat_id | subcat_id | mail | title | text | ...

#2 'countries'
id | country

#3 'categories'
id | cat

#4 'subcategories'
id | cat_id | subcat

iš šių lentelių duomenis traukiu taip:

        SELECT 
            details.date AS date, 
            details.id AS id,
            details.text AS text, 
            categories.cat AS cat, 
            subcategories.subcat AS subcat, 
            countries.country AS country
        FROM details 
        INNER JOIN categories ON categories.id=details.cat_id
        INNER JOIN subcategories ON subcategories.id=details.subcat_id
        INNER JOIN countries ON countries.id=details.country_id
        ORDER BY details.time DESC

viskas veikia lyg ir gražiai, bet pakolkas duomenų nėra daug, nes tik bandymai, tačiau jų turėtų būt tikrai nemažai, ir ar nebus tada problemų? o gal galima čia kaipnors optimizuot? ši lentelių struktūra man patogi, nes tos trys šalutinės lentelės bus taip pat nuolat pildomos.
ir dar klausimas: tokiu pačiu principu noriu padaryti dar vieną užklausą, tik lentelių kiekis bus didesnis: 1 pagrindinė ir 6 šalutinės, ir dar prie kiekvieno JOIN'o dasidėtų po salygą. ar šiuo atvejų būtų teisinga naudot tokiu pačiu principu organizuotą užklausą?

ir dar klausimukas: ar eina kaip nors išvengt tų 'AS', kad viskas vyktų automatiškai, arba bent jau kaipnors labiau patogiau..?

tik dėl asmeninio intereso: kiek visgi realiai JOIN'ų galima panaudot? =]

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

mysql> select * from t1;
+------+------+------+
| s1   | s2   | s3   |
+------+------+------+
|    1 | 1    |    1 | 
|    2 | 2    |    2 | 
+------+------+------+
2 rows in set (0.00 sec)

mysql> select b.s1 a from t1 b;
+------+
| a    |
+------+
|    1 | 
|    2 | 
+------+
2 rows in set (0.00 sec)

del "patogumo" tai pradzia cia, toliau google, ir nuo situacijos :)
http://dev.mysql.com/tech-resources/art … ation.html

Re: duomenys iš dviejų lentelių su join

Ramex wrote:

nežinau kaip kiekvienas JOIN'as veikia užklausos greitį

Tai jeigu tau svarbus greitis, tai duomenų normalizavimas greitį lėtina. Tokiu atveju rekomenduoju duomenis denormalizuoti. Tik nepamiršk, kad šiuo atveju bus sunku juos išlaikyti vientisus.. prarasi daug laiko ir pastangų užtikrindamas jų teisingumą.

Bendru atveju aš nematau, kad mažose sistemose mažas greičio praradimas kažką labai lemtu. Turint omenyje, kad nepatyrę programuotojai aplamai pridaro daug kitų neefektyvių dalykų, kurie ir nulemia bendrą paprastų sistemų greitį.

Kaip ir kodėl stabdo viena ar kita užklausa galima pasiaiškinti pasinaudojant EXPLAIN.

Taip pat mažose sistemose nesunku atlikti bandymus: pasigaminti tiek normalizuotą struktūra tiek denormalizuotą, prikišti daug duomenų, ir paleisti sistemoje paplitusias užklausas matuojant greitį. Tada bus tikrai aišku, kas labiau tinka šiuo aspektu...

Ramex wrote:

ir dar klausimas: tokiu pačiu principu noriu padaryti dar vieną užklausą, tik lentelių kiekis bus didesnis: 1 pagrindinė ir 6 šalutinės, ir dar prie kiekvieno JOIN'o dasidėtų po salygą. ar šiuo atvejų būtų teisinga naudot tokiu pačiu principu organizuotą užklausą?

Taip.

Ramex wrote:

ir dar klausimukas: ar eina kaip nors išvengt tų 'AS', kad viskas vyktų automatiškai, arba bent jau kaipnors labiau patogiau..?

Tai AS naudojimas ir yra skirtas patogumui, be jo daugumoje atveju bus mažiau patogu.

Ramex wrote:

tik dėl asmeninio intereso: kiek visgi realiai JOIN'ų galima panaudot? =]

Nepatvirtintais duomenimis, kiek lenteliu galima joininti:

# MySQL 3.23 - 31 table limit
# MySQL 4.0 - 61 table limit
# MySQL 4.1 - 61 table limit
# MySQL 5.0 - 61 table limit

Re: duomenys iš dviejų lentelių su join

aš visad mysql naudodavau tik todėl, kad tiesiog reikėjo visgi kažkur patogiai saugot duomenis, ir užklausas rašiau "bile tik veiktų" =] dabar kai jau prasidėjo komerciniai projektai, tai truputi išsigandau dėl savo rašymo įpročiu ir supratau, kad reik gilinti sql žinias. ačiū už išsamius atsakymus.

Su sąlyga, kad šūdo nebus...

10 (edited by Ramex 2008-05-30 14:27:39)

Re: duomenys iš dviejų lentelių su join

na viskas kaip ir jasna man čia, išmokau ir su group by, count, sum dirbt, kame reikalas tarp left ir inner join'ų. dabar toks teorinis klausimukas: kaip man organizuot anksciau minėtą DB, kad galėčiau duomenis tam tikrose lentelėse saugot keliom kalbom? pvz čia:

#1 'details'
id | time | date | country_id | cat_id | subcat_id | mail | title | text | ...

#2 'countries'
id | country

#3 'categories'
id | cat

#4 'subcategories'
id | cat_id | subcat

lentelių categories ir subcategories duomenys cat ir subcat būtų keliom kalbom. na aš žinau du variantus: pasidaryti po dar vieną stulpelį kuris reikštų kalbą, ir kievienas įrašas būtų visom reikiamom kalbom, arba pasidaryti atskirą vertimų lentelę. bet nei viena, nei kita neatrodo man pakankamai patogu. pirmas variantas ištraukimo atžvilgiu, o antras - apskritai sunku organizuot visų duomenų mainus, na bent man taip atrodo...

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

Na pradžiai pridėčiau papildomą stulpelį skirtą identifikuoti kalbai. Apjungčiau jį su pagrindiniu lentelės ID į vieną UNIQUE indeksą.. ir  viskas. Paprastai programoje bus žinoma, kuri kalba yra aktyvi, teliks tą papildomą parametra pridėti prie užklausos.

12 (edited by Ramex 2008-05-30 14:27:52)

Re: duomenys iš dviejų lentelių su join

tai kaip aš suprantu, tokiu atveju ID stulpelyje reikšmė galėtų kartotis su sąlyga, kad kalbos identifikatoriaus stulpelyje reikšmės nesikartos su ta pačia ID reikšme..? t.y. galėtų būti taip:

ID | lang | cat
------------------
1   | lt     | produktas
1   |en    | product
2   |lt      | prekė
....

ar teisingai supratau? pas manes ID yra PRIMARY, tai apjungiant juo į UNIQUE nereik to indexo pašalint?

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

Ramex wrote:

ar teisingai supratau?

Taip

Ramex wrote:

pas manes ID yra PRIMARY, tai apjungiant juo į UNIQUE nereik to indexo pašalint?

Nereikia trinti jeigu bus užklausų, kuruose bus naudojamas tik tas vienas ID.

Re: duomenys iš dviejų lentelių su join

na jei aš palieku ID su index'u PRIMARY, tai man neleidžia dubliuoti įrašų, nebent aš blogai sujungiau ID ir LANG į UNIQUE...

Su sąlyga, kad šūdo nebus...

Re: duomenys iš dviejų lentelių su join

Ramex wrote:

na jei aš palieku ID su index'u PRIMARY, tai man neleidžia dubliuoti įrašų, nebent aš blogai sujungiau ID ir LANG į UNIQUE...

Nu jo.. logiška.. jeigu jau PRIMARY tai to lauko neleis dubliuoti..

Pas tave tas ID yra autoincrement ar kaip jis formuojamas?

Gali tekti arba dar dėti papildomą lauką-struktūrą arba atsisakyti ID kaip pirminio rakto ir naudoti tik kaip paprastą INDEX'ą .. čia aišku reikia galvoti kaip jis bus generuojamas.

16 (edited by Ramex 2008-05-30 22:17:01)

Re: duomenys iš dviejų lentelių su join

taip, ID yra autoincrement. turbut teks atsisakyt to. na šiaip aš turiu šiokią tokia funkciją pasirašęs išgauti norimo ilgio stringui iš raidžių ir skaičių, tik nesu garantuotas dėl jo nepasikartojamumo... nors šiuo atveju tai nelabai ir svarbu, nes duomenų konkrečiose lentelėse nebus daug.

Su sąlyga, kad šūdo nebus...