DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   SQL baze podataka - Sponzor: Baze-Podataka.net (http://www.devprotalk.com/forumdisplay.php?f=10)
-   -   Explain Query (http://www.devprotalk.com/showthread.php?t=10188)

webarto 24. 06. 2011. 06: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. 09: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. 12: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. 13: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. 13: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. 14: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. 15: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. 15: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. 17: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. 20: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. 04: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. 09: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. 19: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. 13: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 15:13.

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.