» »

Pomoč pri izdelavi MySQL poizvedbe...

Pomoč pri izdelavi MySQL poizvedbe...

«
1
2

urli ::

Recimo, da imam spodnjo tabelo*...



Želel bi izpisati vse izdelke, ki imajo veliko L ter so modre barve - torej poizvedba mora vrniti Izdelek_1 ter Izdelek_2. Kakšna ideja, kako bi to naredil?

* zadeva je normalizirana in v več tabelah, a da bo enostavneje sem tu zapisal kar v eni - zgornji zapis dobim drugače s poizvedbo

urli ::

... where (ime_atributa='velikost' and vrednost_atributa='L') or (ime_atributa='barva' and vrednost_atributa='modra')


To bo vrnilo tudi Izdelek_3, kar pa ne želim, ker izdelek je sicer modre barve ampak je na voljo le v velikosti S.

6bt9hmDwY ::

imaš prav, joinat moraš na samega (t2) sebe za naslednji atribut, da je konjunkcija.

where (t.ime='aaa' and t.vrednost='bb) and (t2.ime='cc' and t2.vrednost='dd')

Jure14 ::

select id from tabela where ime_atributa='velikost' and vrednost_atributa='L'
intersect
select id from tabela where ime_atributa='barva' and vrednost_atributa='modra'

urli ::

Bom dal kar konkretno tabelo, ker mi še vedno ni jasno...



Tale poizvedba vrne vse zadetke...

SELECT p.id, p.name, a.slug, av.slug FROM products AS p LEFT JOIN product_attributes AS pa ON (p.id = pa.product_id) LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id)




Kako zdaj konkretno zgornjo poizvedbo preoblikovati :), da bo vrnila kar želim - recimo, da mora biti velikost s in barva bela?

Zgodovina sprememb…

  • spremenil: urli ()

6bt9hmDwY ::

ne vem, če mysql popdira intersect, ki zna biti podoptimalen, ker vse podmnožice materializira

nekaj v tem smislu sem mislil, nisem preverjal, če deluje ali ima celo smisel (moralo bi sicer nek zametek), samo petkovsko popoldanski osnutek je, če pomaga vsaj kot izhodišče...

select t1.id
from tabela_atributov t1
inner join tabela_atributov t2
 on t1.id=t2.id
where (t1.ime_atributa='barva' and t1.vrednost_atributa='modra')
 and (t2.ime_atributa='velikost' and t2.vrednost_atributa='L')

Zgodovina sprememb…

styrian ::

Probaj dva ločena SELECT stavka. Prvi naj ima where ime_atributa='velikost' and vrednost_atributa='L'

Drugi pa naj ima where ime_atributa='barva' and vrednost_atributa='modra'

Potem ju združi z UNION

6bt9hmDwY ::

union sicer nastopa kot or - disjunkcija, ker vrača unijo zapisov velikost=L in barva=modra, ne pa preseka, kar op verjetno želi.

kuall ::

mssql, mysql ne znam :D
select*
from products p 
where 

-- make sure produkt je bel
exists (select 1 from product_attributes pa 
join attributes a ...
join attribute_values av ...
where pa.product_id = p.product_id 
and a.name = 'barva'
and av.name = 'bel'
)

-- make sure product je velik S
and exists (...)

styrian ::

6bt9hmDwY je izjavil:

union sicer nastopa kot or - disjunkcija, ker vrača unijo zapisov velikost=L in barva=modra, ne pa preseka, kar op verjetno želi.


Ja, prav imaš. INTERSECT naj uporabi.

6bt9hmDwY ::

styrian je izjavil:

Ja, prav imaš. INTERSECT naj uporabi.

nisem prepričan, da ga mysql že podpira, če preskočimo (domnevno) podoptimalnost...

kuall ::

6bt9hmDwY je izjavil:

ne vem, če mysql popdira intersect, ki zna biti podoptimalen, ker vse podmnožice materializira

nekaj v tem smislu sem mislil, nisem preverjal, če deluje ali ima celo smisel (moralo bi sicer nek zametek), samo petkovsko popoldanski osnutek je, če pomaga vsaj kot izhodišče...

select t1.id
from tabela_atributov t1
inner join tabela_atributov t2
on t1.id=t2.id
where (t1.ime_atributa='barva' and t1.vrednost_atributa='modra')
and (t2.ime_atributa='velikost' and t2.vrednost_atributa='L')



nesmiseln query.
ne more imet atribut z istim idjem različne vrednosti.

styrian ::

6bt9hmDwY je izjavil:

styrian je izjavil:

Ja, prav imaš. INTERSECT naj uporabi.

nisem prepričan, da ga mysql že podpira, če preskočimo (domnevno) podoptimalnost...


Interesect lahko simuliraš:

SELECT DISTINCT id
FROM t1
WHERE id IN (SELECT id FROM t2);

6bt9hmDwY ::

kuall je izjavil:

nesmiseln query.
ne more imet atribut z istim idjem različne vrednosti.

to je id od artikla, kuall...

če bi že hotel celo rešitev napisal, bi napisal polja AtributId (auto), ArtikelId FK, Ime, Vrednost...
join na ArtikelId...

tako zdaj končno tudi ti, Kuall, razumeš, ko se tako podrobno razčleni zadeve?
AtributId ni nujen...

bo šlo?

Zgodovina sprememb…

kuall ::

v queryju imaš samo 2 tabeli, ki sta enaki in ju joinaš po idju. ok pol si se zatipkal in si mislil, da je ena tabela od produktov? ampak nisi se mogel zatipkat, ker ju v where spet obravnavaš kot tabeli atributov.
priznaj, da si skracal nesmisel in nehaj bluzit no. :)

6bt9hmDwY ::

kuall je izjavil:

v queryju imaš samo 2 tabeli, ki sta enaki in ju joinaš po idju. ok pol si se zatipkal in si mislil, da je ena tabela od produktov? ampak nisi se mogel zatipkat, ker ju v where spet obravnavaš kot tabeli atributov.
priznaj, da si skracal nesmisel in nehaj bluzit no. :)

Kuall, bodi konstruktiven... Tabele artiklov nisem vpeljeval, ker ni potrebna za osrednji problem, kar je op spraševal... Samo vrne se referenca na zapis v tabeli artiklov, ne glede na to, kaj vse naredi z njo. Domnevam, da zna op povezati sam, če pa ne zna, bo vprašal ponovno in boš mu ti odgovarjal stvari, ki se meni zdijo sicer samoumevne.

Mimogrede, v queryu je ENA SAMA dejanska tabela, ki ima dva aliasa, premodri Kuall...

Nič, op, Kuall začenja trolat, ker slabo razbira namen. Če imaš težave, pošlji ZS. Jaz v temo več ne bom pisal, da bo prav vsak kekec nekaj trolal.

Zgodovina sprememb…

kuall ::

a nisi zmožen priznat, da je nesmisel? ok. jaz bi bil na tvojem mestu.

6bt9hmDwY ::

Kuall, napravi eksperiment in javi, kaj dobiš.
Potem bova nadaljevala o nesmislih :-)

Tabela: lastnosti,
Polja tabele: id, ime, vrednost

Vrednosti polj po zapisih:
1, barva, modra
1, velikost, L
2, barva, modra
3, velikost, L

Poženi in povej, kaj dobiš
SELECT t1.id
FROM lastnosti AS t1 INNER JOIN lastnosti AS t2 ON t1.id = t2.id
WHERE ((t1.ime='barva') AND (t1.vrednost='modra') AND (t2.ime=velikost') AND (t2.vrednost='L'))

Zgodovina sprememb…

kuall ::

a še zmeraj vztrajaš?
joinaš 2 tabeli po IDju. spodaj pa narediš where tabela1.vrednost is not tabela2.vrednost.
to bo vedno vrnilo nič.
v bistvu je join tabele same na sebe po istem idju vedno nesmisel. lahko po 2 različnih kolonah v tabeli, ne pa po isti.

6bt9hmDwY ::

Preizkusi in do takrat se ne javljaj, junior!

Če ti, junior, ne poznaš stvari, še ne pomeni, da niso možne.

JUNIOR, PREIZKUSI, scenarij imaš napisan.

Saj vem, da ne znaš, junior.
Dobiš 1.
Če v tretjem zapisu spremeniš na 3, dobiš 1 in 3.
Če v četrtem zapisu spremeniš na 2, dobiš 1 in 2.

Zdaj pa spat brez večerje, junior!

Zgodovina sprememb…

kuall ::

ti poskusi, napiše cel query pa ga bomo pognali. kaj bom jaz poskušal tvoje nesmisle in zgubljal čas heh.

6bt9hmDwY ::

kuall je izjavil:

ti poskusi, napiše cel query pa ga bomo pognali. kaj bom jaz poskušal tvoje nesmisle in zgubljal čas heh.

Dragi kuall, ker si res tako omejen in ne razumeš konceptualnih rešitev. Tule, samo zate, junior, osnovni query je zawrapan med prvi ( in zadnji ). Saj vem, da ti nič ni jasno. Če potrebuješ še kak nasvet, kar vprašaj, ti bo op odgovoril...

SELECT * FROM produkti WHERE id IN (
SELECT t1.id
FROM lastnosti AS t1 INNER JOIN lastnosti AS t2 ON t1.id = t2.id
WHERE ((t1.ime='barva') AND (t1.vrednost='modra') AND (t2.ime='velikost') AND (t2.vrednost='L')))

Kuall ni znal tega uporabiti, ojoj, ojoj, ojoj...

Zgodovina sprememb…

kuall ::

pa si pognal? seveda nisi. dej napiši še tabelo in vstavi not par primerov.

pa to je isto kot una tema o sql null. slo tech.:))

ps. namesto joina naredi AND z dvojnim IN pa bo delalo. kar je identično moji rešitvi, z razliko, da uporabiš IN namesto EXISTS, IN je ponavadi počasnejši kot exists.

Zgodovina sprememb…

  • spremenilo: kuall ()

6bt9hmDwY ::

Seveda sem pognal s primeri, junior, kaj pa si mislil. Osnovni query je vračal reference na produkt, ne moreš dat tja exists. Ti nisi znal uporabiti querya, jaz sem ti demonstriral, kako se ga uporabi.

Kaj je z nulli? En biser na forumu je menda, ja, ko pravi, da so nulli v bazah brez zveze...

Nisi to menda tudi ti?

Zgodovina sprememb…

kuall ::

prilimaj še tabelo, da bom še jaz pognal.
v null temi sem imel opravka s podobnmi talenti, kot si ti. da nisi ti un gtfo?

6bt9hmDwY ::

Katero tabelo rabiš?

Ne, (žal) nisem gtfo, sem pa slišal, da je res nek zajeban fucker, težek pogodbenik, skoraj nivoja invictusa, nekaj delajo po tujini za mastne denarje ali nekaj, saj ne vem. Pač legende, po mojem pa lažejo, ker noben IT-jevec ne more zaslužiti več kot 2000 EUR.

Kaj je zdaj s temi nulli v bazah?

kuall ::

rabim obe tabeli nafilani s podatki. kako pa si pognal brez da bi kreirali tabeli s podatki?
pol sem uganil, da si gtfo. se da razbrat iz stila pisanja kar hitro heh.

Zgodovina sprememb…

  • spremenilo: kuall ()

6bt9hmDwY ::

Hočeš reči, da si se samo kregal z mano brez zveze? Sploh nisi nič preverjal?

Produkti
| id | ime       |
| 1  | Kuall     |
| 2  | Junior    |
| 3  | Ne razume |

Lastnosti
| id | ime      | vrednost |
| 1  | barva    | modra    |
| 2  | barva    | modra    |
| 1  | velikost | L        |
| 2  | velikost | S        |
| 3  | velikost | L        |

Zgodovina sprememb…

kuall ::

kakšna tabela pa je to, ko se id ponavlja? id je unikaten.
pa prilimaj sql kodo.

Zgodovina sprememb…

  • spremenilo: kuall ()

6bt9hmDwY ::

Kuall, spet moram razložiti, kar sem že napisal, ker si pozabil - Id je sklic na artikel, lastnosti nimajo svojih idjev, ker za prototip. Če pa ti bo lažje, pa pač preimenuj v item_id ali nekaj. Rešitev ni bila namenjena, da jo ti kar copy/paste v svoje aplikacije.

Ne, nisem gtfo, res ne, to je ena legenda, kot Invictus, jaz mu verjetno še v oči ne bi upal pogledati. Sem pa slišal, da je imel neke resne težave z alkoholom in to. Pa menda je bil precej nemoralen dec, kurbe in to.

Ne bom ti nič limal kode, vsega pa res ne morem narediti namesto tebe :-)

Zgodovina sprememb…

kuall ::

bi delalo, če je id productid.
joina se ponavadi po unikatnem idju, tak da to me je zmedlo.
ok recimo, da si imel ti prav.

urli ::

Hvala obema! Takole na hitro sem preveril spodnjo poizvedbo in mislim, da je to to! Ko utegnem, preverim še kakšno rešitev, da vidim, kako je s performance. Gnezdenje poizvedb mi v osnovi ne diši najbolje (performance?) ampak verjetno drugače tako ne bo šlo?

SELECT p.id, p.name
FROM products AS p 
WHERE
EXISTS
(select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
where a.slug='velikost' and av.slug = 'xs' and p.id = pa.product_id) 
and
EXISTS
(select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
where a.slug='barva' and av.slug = 'crna' and p.id = pa.product_id) 

no comment ::

Meni to zgleda kot klasičen primer, ki kliče po pivot-u. Mogoče ima MySQL tudi kakšno svojo razširitev za to (kot npr. T-SQL, ki je prikazan v točki 1.).

declare @t table (Ime_izdelka nvarchar(20), Ime_atributa nvarchar(20), Vrednost_atributa nvarchar(20))

insert
into @t
values
('Izdelek_1', 'velikost', 'S'),
('Izdelek_1', 'velikost', 'L'),
('Izdelek_1', 'barva', 'modra'),
('Izdelek_2', 'velikost', 'L'),
('Izdelek_2', 'barva', 'modra'),
('Izdelek_3', 'velikost', 'S'),
('Izdelek_3', 'barva', 'modra')

-- 1. T-SQL pivot way
select Ime_izdelka
from (
	select Ime_izdelka, Vrednost_atributa, Ime_atributa
	from @t
	where Vrednost_atributa in ('L', 'modra')	-- načeloma ne bi smelo biti potrebno, če bi imel idente po SKUs 
) as s
pivot (
	max(Vrednost_atributa)
	for Ime_atributa in ([velikost], [barva])
) as p
where [velikost] = 'L'
and [barva] = 'modra'

-- 2. dumb ANSI way
select Ime_izdelka
from (
	select Ime_izdelka
	from @t
	where Ime_atributa = 'velikost'
	and Vrednost_atributa = 'L'
	union all
	select Ime_izdelka
	from @t
	where Ime_atributa = 'barva'
	and Vrednost_atributa = 'modra'
) t
group by Ime_izdelka
having count(Ime_izdelka) = 2

urli ::

urli je izjavil:

Hvala obema! Takole na hitro sem preveril spodnjo poizvedbo in mislim, da je to to! Ko utegnem, preverim še kakšno rešitev, da vidim, kako je s performance. Gnezdenje poizvedb mi v osnovi ne diši najbolje (performance?) ampak verjetno drugače tako ne bo šlo?

SELECT p.id, p.name
FROM products AS p
WHERE
EXISTS
(select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id)
where a.slug='velikost' and av.slug = 'xs' and p.id = pa.product_id)
and
EXISTS
(select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id)
where a.slug='barva' and av.slug = 'crna' and p.id = pa.product_id)


Ne bo ok, pri 7+ atributih (povsem realna možnost za filtre) vse skupaj postane brutalno počasno :(

* atributi se dodajajo seveda dinamično in jih je lahko "neomejeno" (torej ne le velikost, barva... lahko je poljubno), prav tako vrednosti - torej praktično identična zadeva, kot je npr. na mimovrste (glej levi stolpec - parametri) - https://www.mimovrste.com/igre-in-sesta...

*neMeDelat - tvojo rešitev preverim jutri, upam, da bo bolje delovala

Zgodovina sprememb…

  • spremenil: urli ()

kuall ::

ti manjkajo indexi?
povsod kjer je join moraš imeti index in povsod kjer je where tudi
ti execution plan pokaže manjkajoče indexe

urli ::

Indexi so, preverim podrobnosti ampak zanimivo, da do 6 atibutov dela kot šus, če jih je 7 je že 1-2sec, pri 8 pa takoj udari na 10sec+ :|

Ahim ::

urli je izjavil:

Ne bo ok, pri 7+ atributih (povsem realna možnost za filtre) vse skupaj postane brutalno počasno :(

Ce ze testiras razlicne resite sporoci se kako je performancno z veliko podatki ce flatas tabelo tako, da vse atribute in vrednosti spravis v en sam stolpec (z vidika aplikacije bos najbrz na koncu imel JSON stolpec, ki vsebuje en array, ter generated stolpec, ki naredi TEXT iz JSON arrayja, na slednjem pa FULLTEXT indeks), in potem delas MATCH ... AGAINST z vsemi atributi, ki so vneseni v iskalnik (variabilno stevilo).

Za test ne rabis vmesnega koraka z JSONom, ki ti bo samo olajsal editiranje atributov v aplikaciji, ampak ga lahko pripravis kar iz tabele z atributi direktno (zlepi skupaj ime_atributa in vrednost_atributa ter nato GROUP_CONCAT() po izdelku).

urli ::

Poizvedba

SELECT p.id, p.name
 FROM products AS p 
 WHERE
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='velikost' and ( av.slug = 'xs' or av.slug = 'l' or av.slug = 'xs') and p.id = pa.product_id) 
 and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='barva' and av.slug = 'crna' and p.id = pa.product_id) 
  and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='ram' and av.slug = '1' and p.id = pa.product_id) 
   and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='tv' and av.slug = 'test' and p.id = pa.product_id) 
    and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='zaslon' and av.slug = '234' and p.id = pa.product_id) 
     and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='resolucija' and av.slug = '123' and p.id = pa.product_id)
      and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='resolucija' and av.slug = '123' and p.id = pa.product_id) 
       and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='resolucija' and av.slug = '123' and p.id = pa.product_id) 
        and
 EXISTS
 (select 1 from product_attributes AS pa LEFT JOIN attribute_values AS av ON (pa.attribute_value_id = av.id) LEFT JOIN attributes AS a ON (av.attribute_id = a.id) 
 where a.slug='resolucija' and av.slug = '123' and p.id = pa.product_id) 


explain
 https://i.postimg.cc/hcnhsPzb/explain.png

https://i.postimg.cc/hcnhsPzb/explain.png



Zgornja poizvedba traja že skoraj 4sec!

 https://i.postimg.cc/5t8dvW85/pocasi.png

https://i.postimg.cc/5t8dvW85/pocasi.png



Vidi kdo, kje je težava?

Seveda to delam na demo bazi... je le tam ene 6 izdelkov, pa teh 8 atribvutov, torej praktično vse skupaj en velik 0, pa gre že zdaj počasi. Nekaj ni ok :/

* če dam
6x exists --> čas 0.0118sec
7x exits --> čas 0.0671sec
8x exits --> čas 0.495sec
9x exits --> čas 3.969sec
10x exits --> čas 36,2903 sec !!!
...

Zgodovina sprememb…

  • spremenil: urli ()

kuall ::

a nima ta mysql execution plana? če meni kaj dela počasi najprej execution plan vžgem.
drgač če imaš dinamično število filtrov lahko shraniš vmesni rezultat za 1 filter v tmp tabelo (zadetki, idji produktov) in poganjaš v while loopu - za vsak filter poženeš 1 loop. bo manj ponavljajoče kode tako in hitreje tudi najbrž.
pa narediš samo join tmp tabele s tabelo produktov ali pa "and exists in tmp table".

najbrž bi se pa tudi dalo filtre shranit v 1 tabelo in to tabelo nekako joinat - prepuščam bralcu, da razmisli kako.

Zgodovina sprememb…

  • spremenilo: kuall ()

leeon ::

select Ime_izdelka
from ime_tabele
group by Ime_izdelka
having sum(case when Ime_atributa = 'velikost' and Vrednost_atributa = 'L' then 1
        when Ime_atributa = 'barva' and Vrednost_atributa = 'modra' then 1
        else 0 end) = 2

no comment ::

Treba je transponirat. Poglej si kako se to naredi v MySQL. Za T-SQL sem dal že jaz primer. Če ti ne prihajajo vsako sekundo novi artikli v bazo, pač materializiraš takšen transponiran pogled iz katerega je potem select bliskovit. Sicer pa uporabiš varianto, ki sem jo tudi že napisal (leeon-ova je na isto vižo).

no comment ::

Sem šel iz firbca pogledat en moj projekt, kjer moram včasih narediti podoben select. Select, ki sem ga v mojem postu dal kot primer, ki bo deloval na katerikoli SQL bazi (točka 2.), mi poizvedbo po 13 različnih atributih vrne prej kot v 1 sekundi. Tabela z atributi ima blizu 50mio zapisov. Seveda bo stvar nekaj odvisna tudi od podatkov, ampak point je, da za neko štacuno, ki ni ravno amazon, bo to non-issue, če ne boš tega laufal ravno na 386.

DamijanD ::

A se ne bi dalo na tak način (pač za vsak pogoj dodaš en inner join (italics) blok) in dobiš IDje produktov, ki jih pa potem uporabiš v glavnem queriju...
  select distinct p.id 
  from products p

  inner join (select pa.product_id 
	from product_attributes pa
	inner join attribute_values av ON pa.attribute_value_id = av.id
	inner JOIN attributes a ON av.attribute_id = a.id
	where a.slug='velikost' and av.slug = 'xs') f1 on f1.product_id = p.id

  inner join (select pa.product_id 
	from product_attributes pa
	inner join attribute_values av ON pa.attribute_value_id = av.id
	inner JOIN attributes a ON av.attribute_id = a.id
	where a.slug='barva' and av.slug = 'crna') f2 on f2.product_id = p.id

Zgodovina sprememb…

  • spremenilo: DamijanD ()

leeon ::

DamijanD je izjavil:

A se ne bi dalo na tak način (pač za vsak pogoj dodaš en inner join (italics) blok) in dobiš IDje produktov, ki jih pa potem uporabiš v glavnem queriju...
 select distinct p.id 
from products p

inner join (select pa.product_id
from product_attributes pa
inner join attribute_values av ON pa.attribute_value_id = av.id
inner JOIN attributes a ON av.attribute_id = a.id
where a.slug='velikost' and av.slug = 'xs') f1 on f1.product_id = p.id

inner join (select pa.product_id
from product_attributes pa
inner join attribute_values av ON pa.attribute_value_id = av.id
inner JOIN attributes a ON av.attribute_id = a.id
where a.slug='barva' and av.slug = 'crna') f2 on f2.product_id = p.id


zakaj vsi pišete queryje z 10 joini in posledično 10x delate query na eno in isto tabelo? a ni tu nobenega DBA-jevca, ki bi povedal, kako slabo je to iz performančnega vidika?

6bt9hmDwY ::

Tole je res videti z naskokom najboljše
select product_id
from products_attributes
group by product_id
having sum(case when name='velikost' and value= 'L' then 1
        when name= 'barva' and value= 'modra' then 1
        else 0 end) = 2

joini so workaround za pivot, ker v mysql (še?) ni podprt
regeneracija fizične 'pivot' tabele je poglavje zase, ki ni zajeto.

naj še kdo preveri s count+null, bi znalo biti še boljše
select product_id
from products_attributes
group by product_id
having count(case when name= 'velikost' and value= 'L' then 1
        when name= 'barva' and value= 'S' then 1
        else null end) = 2

Zgodovina sprememb…

no comment ::

Problem pri SQL-u je, da lahko nekaj res zgleda z naskokom najbolje... realnost je pa čisto drugačna.

Kot sem rekel, jaz imamo 50mio dataset. Rešitev, ki je navdušila leeona in neMeDelata da rezultat v dveh minutah. Moja v sekundi. V tolažbo, Microsoftov pivot, s katerim lahko napišeš res elegantno poizvedbo, odpove skoraj enako spektakularno (ca. 45s).

6bt9hmDwY ::

ja, fajn :-) problem rešen :-)

Zgodovina sprememb…

bemfa ::

Nazaj v šolo bo treba fanjte. Začnete lahko tukaj: Entity%E2%80%93attribute%E2%80%93value model @ Wikipedia
Posebej zanimivo poglavje: Entity%E2%80%93attribute%E2%80%93value model @ Wikipedia
Lahko se gre tudi na noSQL, ali pa se v SQLu uporabi JSONe, zadnje čase znajo tudi SQL baze s tem dobro delat: https://medium.com/@deltazero/mysql-as-...

no comment ::

edit: nerelevantno, ker je bil post, ki sem mu repliciral, spremenje.

Zgodovina sprememb…

6bt9hmDwY ::

no comment je izjavil:

Dummy vzame 1s, ms pivot 45, tvoja 2min.

Tvoja in ms pivot rešitev bo na relativno kratki tabeli delala dovolj hitro za rezultate v "realnem" času. Ko je amatersku ure konec, je pa treba vsaj vedeti kaj bo naredilo index seek, kaj index scan...

Wow, ok, zelo koristen napotek za podobno primere, se je bilo vredno osmešiti, brez skrbi. Me celo preseneča, da je 'moj' (žal si ne smem pripisovati zaslug, mi pa izgleda najlepši) pristop še vedno tako učinkovit proti mssql pivot funkciji. Takšnega načina shranjevanja sicer skoraj ne uporabljamo, razen za eno embedded app, nekoč davno, c-tree baza ali nekaj.

Ne, ne, vse je cool, no comment, navadno sem sicer jaz tisti, ki stvari pohitri na delček izvajanja predhodnega časa, ampak ok, je potrebno stisniti zobe tu in tam...

Zgodovina sprememb…

«
1
2


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Neveljaven mysql stavek - napaka #1054 - Unknown column 'PRODUCTS.TAXCAT' in 'on clau

Oddelek: Programiranje
102170 (2044) MrStein
»

podatkovne baze pomoč

Oddelek: Programiranje
193051 (2604) kr?en
»

Baza & c#

Oddelek: Programiranje
214156 (3214) xardas
»

podatkovna baza

Oddelek: Programiranje
52040 (1861) scarymovie
»

baze podatkov

Oddelek: Programiranje
91564 (1483) urkrajnc

Več podobnih tem