[ Tyler Durden @ 18.01.2010. 08:51 ] @
Recimo da imam jednu bazu o korisnicima koja je relativno velika.
Relevantni podaci o korisniku su rašireni u nekoliko tabela kao i podaci koji su indirektno vezani za tog korisnika (više od 7-8).
Pitanje - jednim upitom ne mogu nikako da izvučem sve što mi treba za tog korisnika, čak bi mi trebalo nekoliko upita ako bih želio sve podatke vezane direktno ili indirektno za tog korisnika.
Da li je to pogrešan dizajn ili ovo u suštini nije toliki problem koliko sam se ja istripovao?
[ franjo_tahi @ 18.01.2010. 10:07 ] @
Imam relativno nov auto, sa relatovni malo kilometara koji relativno dobro radi osim kad ne radi.

Može li mi tko pomoći da ga popravim?

:) :) :)

Ako kažeš što te tmočno muči, koja je struktura baze... možda ti netko pomogne...
[ Tyler Durden @ 18.01.2010. 10:38 ] @
Stvarno ne mislim da sam bio tako uopšten, a i napisao sam da se radi o konceptualnom pitanju. Iako, naravno jeste vezano za konkretnu bazu.
[ jablan @ 18.01.2010. 12:49 ] @
Pa bio si prilično uopšten. Na tom uopštenom nivou, ja mogu reći da nije pogrešan dizajn (opet, ne govorim o tvom konkretnom dizajnu jer ga ni nisi izložio konkretno). Ako je baza normalizovana kako treba, dizajn je dobar. U denormalizaciju baze se ide u slučaju da postoji potreba (slabe performanse npr.), ali tvoja poruka ne nagoveštava da si ti u takvoj situaciji.

Pored toga, šta znači "sve što mi treba u vezi korisnika"? Koliko često ti trebaju svi ti podaci? Da li ih keširaš negde? Mnogo pitanja od kojih zavisi odgovor na tvoje uopšteno pitanje, tako da nije skroz promašio Franjo sa svojom analogijom... :)
[ captPicard @ 18.01.2010. 13:18 ] @
Šta ti nije lakše dati ovdje dizajn baze i primjer izlaza upita koji ti treba pa da ti odgovorimo?
[ Tyler Durden @ 18.01.2010. 14:51 ] @
Ovo je samo dio baze, ali na ovome moze da se vidi sta mislim.
Radi se MySQL-u konkretno.

Imam nekoliko kupljenih paketa u tabeli kupljeni_paket, koji su za razlicite usluge, ali isti korisnik (user_id).
Kako da dobijem sve kupljene paketa za isti user_id, zajedno sa nazivom tog paketa i svim atributima tog paketa.
[ jablan @ 18.01.2010. 15:50 ] @
http://dev.mysql.com/doc/refman/5.0/en/join.html

BTW, polja u tabelama koja se zovu atr1, atr22 itd su obično znak lošeg projektovanja.
[ Tyler Durden @ 18.01.2010. 16:02 ] @
Ne, ne zovu se tabele bas tako :) To sam samo tako stavio kao primjer i da pokazem su potpuno razliciti atributi u pitanju, tako da ne mogu u jednu tabelu paket.

Znam join do nekog nivoa, ali ne mogu da izmozgam kako bi izgledao za moj slucaj.
Samo da jos jednom napomenem sta zelim.
Korisnik ima 2 paketa, jedan iz tabele game_paketi, drugi iz tabele lame_paketi.
Sa jednim upitom treba da vratim sve podatke iz tabele kupljeni_paket za oba kupljena paketa + ime paketa iz tabele game_paket za prvi paket (posto je prvi kupljeni paket definisan u toj tabeli) u prvom rekordu, a u drugom rekordu isto to samo sto mi treba ime paketa iz tabele lame_paket (posto je drugi kupljeni paket za tog korisnika definisan u tabeli lame_paket).

Ti kazes da je to moguce sa jednim upitom?
[ jablan @ 18.01.2010. 16:39 ] @
Pa, kao prvo, činjenica da ime paketa imaš i u jednoj i u drugoj tabeli znači da ti baza nije normalizovana kako treba (tj. treba da imaš jednu "parent" tabelu paketi koja će sadržati ime paketa, koji je zajednički atribut za sve vrste paketa).

Kao drugo, jeste moguće jednim upitom, samo što gornja činjenica komplikuje stvari:
Code (sql):
SELECT k.foo, k.bar, COALESCE(g.name, l.name, '') AS name
FROM kupljeni_paketi k
LEFT JOIN lame_paketi l ON k.paket_id = l.paket_id
LEFT JOIN gama_paketi g ON k.paket_id = g.paket_id

nešto na tu foru
[ Zidar @ 18.01.2010. 18:11 ] @
A ko ne razumes sta je Jablan napisao, mozda je ovo citljivije:

Code:

SELECT A.KupacID, A.PaketID, B.ImePaketa, A.Kolicina
FROM kupljeni_paketi AS A
JOIN Game_Paket AS B ON A.PaketID = B.PaketID
WHERE A.KupacID= X

UNION

SELECT A.KupacID, A.PaketID, B.ImePaketa, A.Kolicina
FROM kupljeni_paketi AS A
JOIN Lame_Paket AS B ON A.PaketID = B.PaketID
WHERE A.KupacID= X


Treba u stvari bez WHERE, ali mislim da je ovako lakse za razumevanje.

Ako MySQL nema UNION, onda ovo nece moci :-( ostaje ti da razumes LEFT JOIN i ono COALESCE ili ekvivalentnu funkciju u MySQL




[ Tyler Durden @ 18.01.2010. 20:20 ] @
Citat:
jablan: Pa, kao prvo, činjenica da ime paketa imaš i u jednoj i u drugoj tabeli znači da ti baza nije normalizovana kako treba (tj. treba da imaš jednu "parent" tabelu paketi koja će sadržati ime paketa, koji je zajednički atribut za sve vrste paketa).

Kao drugo, jeste moguće jednim upitom, samo što gornja činjenica komplikuje stvari:
Code (sql):
SELECT k.foo, k.bar, COALESCE(g.name, l.name, '') AS name
FROM kupljeni_paketi k
LEFT JOIN lame_paketi l ON k.paket_id = l.paket_id
LEFT JOIN gama_paketi g ON k.paket_id = g.paket_id

nešto na tu foru


LEFT JOIN lame_paketi l ON k.paket_id = l.paket_id

Hm, paket_id iz tabele kupljeni_paket nije id paketa iz tabele lame_paket (ili tabele game_paket). paket_id iz tabele kupljeni_paket je vezan za id u tabeli paketi.
Ali takodje sam htio da pitam pa sam zaboravio, da li je ova shema ok.
Definitivno cu da prebacim ime_paketa u tabelu paketi, vidio sam taj problem i prije ali nije mi palo na pamet u tabeli paketi drzim ime_paketa.

Hocu jos malo da proucim ovaj upit....
[ Tyler Durden @ 18.01.2010. 20:23 ] @
Da, zaboravih...
Tabela kupljeni_paket bi trebala da ima nekoliko miliona rekorda, mozda i vise.
Koliko bi se brzo izvrsavali ovako komplikovani upiti ili koriscenje unija?
[ jablan @ 19.01.2010. 08:15 ] @
1) Upiti uopšte nisu komplikovani.
2) Samo napravi indekse, o brzini ćeš brinuti ako se pokaže da program radi sporo.

BTW, opet tražiš konkretan odgovor na uopšteno pitanje. :)
[ Tyler Durden @ 19.01.2010. 10:47 ] @
Ovo pod 2) što si odgovorio, zar to nije naopako i pogrešno razmišljanje. Treba odma u startu sve da uradim što je bolje moguće, kako bi kasnije imao manje glavobolja?
Ma zadovoljan sam i sa uopštenim odgovorima :)

Još jedno generalno pitanje i jedno konkretno.
Da li ovaj dio baze izgleda ok?

I ne znam da li je previđen ovaj moj prethodni post, ali ne mogu direktno da se spajaju tabele kupljeni_paket i tabele lame_paketi ili game_paketi već samo preko tabele 'paketi'.
[ dragancesu @ 19.01.2010. 14:29 ] @
Iskreno uzasavam se komplikovanih upita, mnogo puta se moze to uraditi korektno ali kad upit dodje do desetak redova mislim da ga treba razbiti na manje.

Ajmo malo teoretski. Sa napomenom da ne koristim mySQL i ne znam kako barata sa view-ovima.

Problem nije neuobicajen, da je forma reklo bi se master-detail, postoji jedna maticna tabela (za primer user je jedinstven) i druge prometne tabele (gde se user nije jedinstven ). Normalizacija je posebna prica i to se odradjuje kako se odradjuje.

Znaci master tabela je user_id, user_ime, ...
Detail tabela je user_id, paket_id, operator_id, datum_unosa, ... i ostale detail tabele.

U principu se zna kakvi se upiti traze pa se onda napravi jedan view gde ce biti grupisano po user_id, paket_id... (VIEW1)
VIEW2 kao view1 ali sa filterom za datum,
VIEW3 kao view1 ali sa filterom za aktivnost,
VIEW4 kao view1 ali sa filterom za placanje, ...

I onda se upit svede na vezu master-view1 , master-view2, master-view3, ... gde je zajednicko polje user_id.

OK, jedan slozen upit ako treba nesto ad-hoc, ali ako se ima vremena i zna se sta treba onda se problem razbije na nekoliko delova i olaksa.

A za prethodni post. Kako je dizajnirano deluje da ne moze, Ali ako se napravi tabela paket i samo doda polje vrsta paketa L(ame), G(ame) onda bi moglo.
[ jablan @ 19.01.2010. 14:58 ] @
Citat:
Tyler Durden: Ovo pod 2) što si odgovorio, zar to nije naopako i pogrešno razmišljanje. Treba odma u startu sve da uradim što je bolje moguće, kako bi kasnije imao manje glavobolja?

Hehe, opet uopšteno pitanje sa zahtevom za konkretnim odgovorom... :) U principu, postoji nešto što se zove "premature optimization" i što se smatra lošom praksom (Knut je rekao da je prerana optimizacija zlo svih zala). Naravno, ovo ne treba shvatiti bukvalno u smislu da možeš da radiš šta hoćeš, već da za početak treba da se fokusiraš na što jednostavnije i elegantnije rešenje svog problema, koje ćeš kasnije da usložnjavaš ako okolnosti budu zahtevale.

RE indirektnog spajanja, ništa, to ti je još jedan JOIN u gornjem upitu.