Parent - child fetch problem
Imam dve tabele:
items id item-a i parent koji moze biti -1 ako item nema parenta ili itemid ako ima parenta tabela sadrzi sve iteme. itemid | parent --------------- owners_items ownerid je id osobe koja poseduje item itemid je veza sa tabelom items ownerid | itemid ---------------- Problem je sledeci, treba izvuci sve iteme koje ne poseduje owner (prilicno prosto za sada). Ali onda dodje problem :) Ukoliko item ima parenta, treba proveriti da li owner poseduje njegovog parenta, ako ne poseduje item ne treba da bude izvucen, ako poseduje treba. Any ideas, help etc? |
Hajde pojasni opet onaj deo "ako item ima parenta"
Item ima parenta, parent pripada owneru -> Item jeste u skupu rešenja ili ne? |
Item moze da bude parent drugom itemu.
Item ima parenta, parent pripada owneru -> Item jeste u skupu rešenja ili ne? jeste (ali njegov parent nije, posto ne trebaju da se prikazu itemi koje owner poseduje) |
Sad, možda ja ne vidim veliku sliku :), ali:
Kôd:
Select * From Items Where ItemID Not In ( |
Poenta je, ako item ima parent-a znaci da nije "stand-alone", vec upgrade nekog vec postojeceg itema (njegovog parent-a).
Stastavlja se lista itema koje osoba moze da kupi, ako nije vlasnik parent itema, nemoze da kupi child item (nece mu se prikazati u listi) dok ne kupi parent item. Nadam se da sam bio jasnij :/ :) PS posto owners_items ima negde oko 2mil rekorda, IN nije bas lepo :D Kôd:
select items.* from items left join owners_items on (items.id = owners_items.itemid and owners_items.ownerid= $ownerid) |
Evo resenja
Kôd:
( |
Hm, hajde prvo koncepcijski da dođemo do rešenja; a performanse posle (ako postoje odgovarajući indeksi po polju za koji radiš NOT IN ili IN, pametan SQL engine će to fino odraditi i bez prolaska kroz 2M slogova, pogotovo ako je IN podskup dovoljno mali, što izgleda da je slučaj).
Znači, treba da dobiješ sve elemente za koje važi: - owner ga ne poseduje i oni nemaju parenta ili - owner poseduje parenta ali ne poseduje child element Nekako ovako: Kôd:
Select * From Items Where |
Da to deluje OK. To je otprilike isto sto sam napisao i ja gore (samo bez dodatnih uslova, koji nisu ni bitni :) za ovu polemiku).
Samo je fora (zasto izbegavam IN) Select ItemID from owners_items where ownerid = :ownerInQuestion u teoriji moze da vrati do 0.5mil redova. I ja kazem and parent in (select items.itemid from items left join owners_items on (items.id = owners_items.itemid and owners_items.ownerid = $ownerid) where owners_items.itemid is not null ) sto mi se ni malo ne dopada. |
Pa, sa obe strane priče imaš velike skupove podataka: ako jedan owner može da ima i do 0.5M slogova, to znači da items-a ima koliko hoćeš.
U svakom slučaju, performanse treba dobro testirati na živom skupu podataka i to na oba kraja: za ownere koji imaju jako malo itema, kao i za ownere koji imaju jako puno itema. Uz explain plan za oba krajnja uslova, možda može da se iskopa i bolje rešenje. |
trenutne cifre su owner-a 5mil item-a 1,1mil (upravo uradio count).
Itemi se sheruju znaci vlasnik jedan isti item moze da poseduje svaki owner, tako da dodjemo do toga da je maksimalan broj rekorda u owners_items (u teoriji) 5mil*1.1mil = 5500000000000 |
To je ok, ali sam shvatio da je u ovom upitu određeni owner fiksiran i da neće doći do Dekartovog proizvoda :)
Testiraj upit za tog što ima 5 Mil, čisto da vidimo koliko DB enginetu treba ;) |
ocekuj sutra, posto nemam pristup pravim podacima van vpn-a... a ovde ga nemam :)
|
sad sam se setio :) imam ssh do masine koja ima vpn :)
8.16sec (za moj query) |
Nije to strašno :) Lepo animiran Flash satić :-P i rešen problem :)
Šalim se, definitivno mora optimizacija ili razbijanje na više upita ili više logike na front endu. Trenutno mi ne pada na pamet šta, ali 8 sec je previše. |
Vreme je GMT +2. Trenutno vreme je 22:01. |
Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.