Autor Zpráva
xlifer
Profil
Reším situaci, kdy mám tabulku zboží a parametry.

CREATE TABLE zbozi (
pk int(11) auto_increment,
kod varchar(32),
kategorie int(11),
nazev varchar(255),
PRIMARY KEY  (pk),
UNIQUE KEY (kod)
)

CREATE TABLE parametry (
pk int(11) auto_increment,
kod_zbozi varchar(32),
parametr varchar(64),
PRIMARY KEY  (pk),
INDEX (kod_zbozi)
)

Zápisy v tabulce "parametry" jsou vždy na základě kódu zboží a odpovídá tomu sloupec "kod_zbozi". Až sem žádný problém.

Ale v případě, ze chci udělat výběr zboží z tabulky "zbozi" na základě navolených parametrů (ve filtru výpisu zboží na stránce), tak nevím zda lze dotaz pro výběr postavit jinak než přes vnořené SELECTy?

Protože a pochopitelně v tabulce "parametry" může být k jednomu zboží více parametrů a když si navolím ve filtru pro výběr zboží více hodnot, tak nastává "oříšek" jak udělat co nejlépe výběr.

Funguje mi to níže uvedeným způsobem přes vnořené SELECTy, ale zda to lze vytvořit lépe s tím bych eventuálně potřeboval trochu poradit zde od zkušenějších a předem děkuji za všechny rady.

SELECT zbozi.kod, zbozi.nazev FROM zbozi JOIN parametry ON parametry.kod_zbozi = zbozi.kod WHERE zbozi.kategorie = 'nejake_cislo' AND ((SELECT parametry.pk FROM parametry WHERE parametry.kod_zbozi = zbozi.kod AND parametry.parametr = 'param1' LIMIT 1)>0 AND (SELECT parametry.pk FROM parametry WHERE parametry.kod_zbozi = zbozi.kod AND parametry.parametr = 'param2' LIMIT 1)>0) GROUP BY zbozi.kod ORDER BY zbozi.nazev
Keeehi
Profil
SELECT kod_zbozi AS kod FROM parametry WHERE parametr IN ('param1','param2') GROUP BY kod_zbozi HAVING count(*) = 2
Tento dotaz vybere kódy zboží, které mají oba parametry. Předpokládá, že jeden parametr nemůže být přiřazen jednomu výrobku vícekrát.

No a podle toho se už dá provádět filtrování. Buď joinem nebo ve where. Netuším, co bude lepší, to si budete muset otestovat.
SELECT kod, nazev FROM (/*předchozí dotaz*/) JOIN zbozi USING (kod).
SELECT kod, nazev FROM zbozi WHERE kod IN (/*předchozí dotaz*/).
xlifer
Profil
Keeehi:

Díky za tip. Takže bez vnořeného SELECTu to objeít stejně nelze. Nicméně Váš návrh si vystačí s jedním vnořeným SELECTem, narozdíl od mého řešení, kdy jsem na každý parametr vykonávál podmínku zvlášť. Teď je otázkou, zda při vetším počtu parametrů není původní dotaz výkonější, ale asi ne, je to pouze úvaha.
juriad
Profil
Vystačí si úplně bez vnořených dotazů. Nic ti nebrání si v tom „vnitřním“ dotazu vybrat i název. Pak ten vnější už nepotřebuješ.
Ten způsob, že si vybereš ve vnitřním dotazu jen kody je vhodný kvůli klauzuli GROUP BY. Podle standardu bys totiž musel v GROUP BY vyjmenovat všechny soupečky, které má dotaz vrátit (nebo na ně aplikovat agregační funkci).
Kajman
Profil
První varianta s vnořeným dotazem zamezí špatnému plánování. Nazev je v jiné tabulce, proto nalezené kódy spojuje Keeehi s tabulkou zbozi. Je možné použít group by na celém joinu, ale jistější je to takto.

Kdysi to v podobném tématu dopadlo lépe s joinováním poddotazu.
xlifer
Profil
Ještě jsem narazil na jeden problém. Rozšířil jsem tabulku parametry o sloupec "typ", který určuje typ parametru, takže teď neplatí pravdilo, že každá hodnota může být přiřazena jednomu zboží pouze jednou, ale vícekrát, myšleno typem parametru.

Příklad:

Délka: 400
Šířka: 400

Pak když si ve filtru vyberete parametr délka, tak přes výběr pomocí IN (param1,param1) se vybere zboží špatně, protože bude odpovídat také šírka, resp. oba parametry jsou 400, ale každý jiný typ.

Nenapadá mě jak lze spojit výběr IN ještě s typem parametru?
Keeehi
Profil
Tam už porovnáváš dva sloupce, takže to musíš ručně rozepsat:
WHERE parametr (typ = 'delka' AND hodnota = 400) OR (typ = 'šířka' AND hodnota = 400) OR ...
xlifer
Profil
Keeehi:
Jasně chápu, chtěl jsem najít způsob jak se vyhnout dlouhému dotazu WHERE xx AND yy OR xx AND yy.

Napadlo mě snad ještě řešení, že bych přidal ještě sloupec do tabulky parametry - "parametr_spoj", který by obsahoval spojení typ+hodnota a pak bych mohl použít ten úhlednější dotaz výběru přes IN.

Příklad:

delka.400
sirka.400

SQL:

parametr_spoj IN ('delka.400', 'sirka.400')

nebo uvádět typ číslicemi:

parametr_spoj IN ('1.400', '2.400')

V tabulce parametry pak přídat na sloupec "parametr_spoj" INDEX.

Akorát je otázka, zda to není zbytečné komplikované řešení a na vykonání výběru to zabere stejný čas jako dotazem xx AND yy OR xx AND yy.
juriad
Profil
xlifer:
Můžeš použít IN pro dvojici (n-tici) hodnot zároveň:
WHERE (typ, hodnota) IN (('delka', 400), ('šířka', 400))
xlifer
Profil
juriad:
Moc díky! To je přesně co potřebuji a vyhnu se "zdlouhavému dotazu" podmínek AND, OR.

Vyzkoušeno... Funguje to perfektně!
rafej
Profil
juriad:
Zajímavý tip. Díky. Nad více sloupci jsem se s tím ještě nepotkala.

Má to nějaký háček, na kterém by si člověk mohl nabít ústa? Např. povolená hodnota NULL v jednom ze sloupců?

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: