Forum » Programiranje » Pomoč pri izdelavi MySQL poizvedbe...
Pomoč pri izdelavi MySQL poizvedbe...
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
Ž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')
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'
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...
Kako zdaj konkretno zgornjo poizvedbo preoblikovati , da bo vrnila kar želim - recimo, da mora biti velikost s in barva bela?
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...
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…
- spremenilo: 6bt9hmDwY ()
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
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 ::
kuall ::
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 ::
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…
- spremenilo: 6bt9hmDwY ()
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. :)
priznaj, da si skracal nesmisel in nehaj bluzit no. :)
6bt9hmDwY ::
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…
- spremenilo: 6bt9hmDwY ()
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'))
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…
- spremenilo: 6bt9hmDwY ()
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.
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!
Č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…
- spremenilo: 6bt9hmDwY ()
kuall ::
ti poskusi, napiše cel query pa ga bomo pognali. kaj bom jaz poskušal tvoje nesmisle in zgubljal čas heh.
6bt9hmDwY ::
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…
- spremenilo: 6bt9hmDwY ()
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.
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?
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…
- spremenilo: 6bt9hmDwY ()
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?
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?
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.
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
Lastnosti
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…
- spremenilo: 6bt9hmDwY ()
kuall ::
kakšna tabela pa je to, ko se id ponavlja? id je unikaten.
pa prilimaj sql kodo.
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 :-)
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…
- spremenilo: 6bt9hmDwY ()
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.
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 ::
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
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 ::
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
explain
Zgornja poizvedba traja že skoraj 4sec!
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 !!!
...
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
Zgornja poizvedba traja že skoraj 4sec!
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.
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 ::
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
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 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…
- spremenilo: 6bt9hmDwY ()
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).
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).
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-...
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…
- spremenilo: no comment ()
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…
- spremenilo: 6bt9hmDwY ()
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Neveljaven mysql stavek - napaka #1054 - Unknown column 'PRODUCTS.TAXCAT' in 'on clauOddelek: Programiranje | 2169 (2043) | MrStein |
» | podatkovne baze pomočOddelek: Programiranje | 3051 (2604) | kr?en |
» | Baza & c#Oddelek: Programiranje | 4156 (3214) | xardas |
» | podatkovna bazaOddelek: Programiranje | 2040 (1861) | scarymovie |
» | baze podatkovOddelek: Programiranje | 1564 (1483) | urkrajnc |