- -
Explain Query
(
http://www.devprotalk.com/showthread.php?t=10188)
webarto |
24. 06. 2011. 05:24 |
Explain Query
Please :)
Ovako imam pitanje u vezi querya, radi se o pretrazi atributa, pretražuju se atributi sa id brojem 6 i 8, queryi rade ali ne kako očekujem...
1.
PHP kôd:
SELECT * FROM resource_attributes WHERE (attribute_value LIKE '%La%' AND attribute_id = 6) [b]AND[/b] (attribute_value LIKE '%Ho%' AND attribute_id = 8) GROUP BY resource_id
Ovo radi kada se umjesto AND stavi OR, ali onda dobijam djelomičnu pretragu, jer oba uslova (zagrade) moraju biti zadovoljena u slučaju da je OR onda je dovoljno samo jedan. U slučaju da je AND explain vraća Impossible WHERE...
2.
PHP kôd:
SELECT * FROM resource_attributes WHERE (attribute_value LIKE '%La%' OR attribute_value LIKE '%Ho%') AND attribute_id IN(6,8) GROUP BY resource_id
Ovo radi OK, ali "La" može biti atribut 8 a mora biti atribut 6 i obrnuto.
Pitanje je kako da atribut 6 bude "La" i atribut 8 bude "Ho" i oba uslova budu zadovoljena inače da ne vrati ništa :)
Riješio sam ovo na drugi način jer ima još komplikacija ali me čisto zanima gdje griješim. Hvala.
Tabela:
|
jablan |
24. 06. 2011. 08:06 |
Citat:
Originalno napisao webarto
(Napišite 100225)
oba uslova (zagrade) moraju biti zadovoljena u slučaju da je OR onda je dovoljno samo jedan.
|
Kako mogu oba da ti budu zadovoljena? Polje attribute_id može biti ili 6 ili 8, ne može biti i 6 i 8 u isto vreme.
Šta ustvari želiš da dobiješ kao rezultat? Po meni, čini se da ti upravo treba ova prva varijanta sa ((AND) OR (AND)).
|
webarto |
24. 06. 2011. 11:58 |
Ma ne, znam da ne može i treba da ne može, već ovakva je situacija...
resource_id attribute_id attribute_value
1 6 La Iruela
1 8 Hotel
2 8 Hotel
Potreban mi je query, da mi vrati ovaj resource_id da je 1 ako i samo ako atribut 6 sadrži "La" a atribut 8 sadrži "Ho"... ako recimo postoji atribut 8 sa "Ho" a ne postoji atribut 6 sa "La", query bi trebao da vrati ništa. Nadam se da me razumiješ. Hvala.
|
jablan |
24. 06. 2011. 12:07 |
A pa ne može to tako onda.
Uradi inner join tabele na samu sebe preko resource_id, gde ćeš u where da staviš da leva strana joina ima 6-La, a desna 8-Ho.
Btw, LIKE 'Ho%' je mnogo brže od LIKE '%Ho%', imaj to u vidu.
|
webarto |
24. 06. 2011. 12:23 |
:)
Ja sam to ovako bio ali mi "ružno" izgleda pogotovo što se pretražuju još par atributa osim ova 2...
PHP kôd:
SELECT t1.resource_id FROM resource_attributes AS t1 LEFT JOIN resource_attributes AS t2 ON t1.resource_id = t2.resource_id LEFT JOIN resource_attributes AS t3 ON t1.resource_id = t3.resource_id WHERE (t2.attribute_value LIKE '%La%' AND t2.attribute_id = 6) AND (t3.attribute_value LIKE '%Ho%' AND t3.attribute_id = 8) GROUP BY t1.resource_id
Znam za Indexe to sam stavio samo reda radi, napravit ću autocomplete iz postojećih vrijednosti u bazi tako da može biti i = umjesto bilo kakvog LIKE, hvala. Ovaj query sa JOIN + LIKE se izvršava za 0.0002s...
|
jablan |
24. 06. 2011. 13:47 |
Imaš tu jedan join viška. U suštini, treba ti ovo (pretpostavljam):
Kôd:
SELECT *
FROM resources r
LEFT JOIN resource_attributes a_6 ON r.id = r.resource_id AND a_6.attribute_id = 6
LEFT JOIN resource_attributes a_8 ON r.id = r.resource_id AND a_8.attribute_id = 8
WHERE
a_6.attribute_value LIKE 'La%'
AND a_8.attribute_value LIKE 'Ho%'
Nema potrebe za GROUP BY.
|
webarto |
24. 06. 2011. 14:09 |
Kako si znao da je tabela resources :D
Malo sam prepravio, to je to, svaka čast.
PHP kôd:
SELECT r.id FROM resources r LEFT JOIN resource_attributes a_6 ON r.id = a_6.resource_id AND a_6.attribute_id = 6 LEFT JOIN resource_attributes a_8 ON r.id = a_8.resource_id AND a_8.attribute_id = 8 WHERE a_6.attribute_value LIKE 'La%' AND a_8.attribute_value LIKE 'Ho%'
|
jablan |
24. 06. 2011. 14:25 |
To je konvencija koju uostalom fura i ActiveRecord (ORM za Rails). BTW, ako ti zaista treba samo id tog resursa (a ne i ostala polja), nema potrebe da se joinuje sa tom tabelom, nego samo:
Kôd:
SELECT a_6.resource_id
FROM resource_attributes a_6
INNER JOIN resource_attributes a_8 ON a_6.resource_id = a_8.resource_id
WHERE
a_6.attribute_id = 6
AND a_8.attribute_id = 8
AND a_6.attribute_value LIKE 'La%'
AND a_8.attribute_value LIKE 'Ho%'
|
dacha |
24. 06. 2011. 16:49 |
Citat:
Originalno napisao webarto
(Napišite 100225)
Please :)
1.
PHP kôd:
SELECT * FROM resource_attributes WHERE (attribute_value LIKE '%La%' AND attribute_id = 6) [b]AND[/b] (attribute_value LIKE '%Ho%' AND attribute_id = 8) GROUP BY resource_id
|
Ovo tvoje može da radi, bez višestrukih JOIN-a, baš sa OR, ali da izdvojiš samo one zapise koji imaju obadva uslova zadovoljena.
Kôd:
SELECT *, COUNT(*) as broj_atributa FROM resource_attributes
WHERE
(attribute_value LIKE '%La%' AND attribute_id = 6)
OR
(attribute_value LIKE '%Ho%' AND attribute_id = 8)
GROUP BY resource_id
HAVING broj_atributa = 2
|
webarto |
24. 06. 2011. 19:54 |
@jablan, dobar taj RoR :D Treba mi još kolona to sam ja stavio ID da ne komplikujem, hvala ti i na drugoj soluciji.
@dacha, dobar fazon, nikad mi ne bi palo na pamet :)
|
dacha |
25. 06. 2011. 03:18 |
Citat:
Originalno napisao webarto
(Napišite 100235)
PHP kôd:
SELECT r.id FROM resources r LEFT JOIN resource_attributes a_6 ON r.id = a_6.resource_id AND a_6.attribute_id = 6 LEFT JOIN resource_attributes a_8 ON r.id = a_8.resource_id AND a_8.attribute_id = 8 WHERE a_6.attribute_value LIKE 'La%' AND a_8.attribute_value LIKE 'Ho%'
|
Ako je ovo u pitanju - da su ti potrebni podaci iz tabele resources, a podaci iz tabele resource_attributes služe samo za uslov, onda ovoj tabeli nije mesto u FROM već u WHERE. Ovako bih ja uradio ovo što si ti iznad:
Kôd:
SELECT r.id
FROM resources r
WHERE
2 = ( SELECT COUNT(*) FROM resource_attributes ra
WHERE
ra.resource_id = r.id
AND
( attribute_value LIKE '%La%' AND attribute_id = 6
OR
attribute_value LIKE '%Ho%' AND attribute_id = 8))
Ako tabela resource_attributes nije velika i uslov sadrži samo nekoliko atributa, onda je svejedno kako ćeš uraditi (sa JOIN ili ovako). Ali, junction tabele uglavnom sadrže stotine hiljada zapisa (resources x atributes), pa ako se pretraga vrši po malo više atributa, onda će JOIN napraviti set sa milionima zapisa i performanse će biti lošije.
|
jablan |
25. 06. 2011. 08:03 |
^ Gornji LEFT JOIN će imati tačno onoliko zapisa koliko postoji u resources tabeli. Plus je potpuno logično rešenje pošto simulira proširenje tabele resources custom atributima.
|
dacha |
25. 06. 2011. 18:36 |
Ne, nisam mislio u konkretnom slučaju, naveo sam ovo baš zbog logike koju pominješ. Meni je logično (i semantički ispravno) da u FROM idu one tabele iz kojih se uzimaju podaci za konačni set zapisa (i naravno one koje su neophodne za njihovo povezivanje), a onim tabelama čiji podaci služe samo kao uslov logično mesto je u WHERE. Gore sam hteo da kažem da se, stavljanjem ovih tabela u FROM ponekad pravi ogroman set zapisa bez potrebe.
Naravno, meni je ovo logično, ne znači da je tako. :)
|
webarto |
26. 06. 2011. 12:56 |
Da, LEFT JOIN kako ga je jablan napisao vraća tačno resurse recimo 10 i 12, znači 2 reda, bez GROUP BY, isto kao i ovaj drugi tvoj (bez GROUP BY), za isto vremena jer je tabela mala. Hvala ;)
|
Vreme je GMT +2. Trenutno vreme je 08:10. |
|
Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.
Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.