Autor Zpráva
regy
Profil
Ahoj,
nenapadlo mě žádné řešení, jak by následující věc šla vyřešit jedním dotazem. Proto prosím vás zkušenější o nastínění.
mám např. tabulky:

knihy
ID | NAZEV
-----------------
 1 | První knížka
 2 | Druhá knížka

knihyvlastnosti
ATRIBUT     | HODNOTA
---------------------
pocetstran1 | 250
pocetstran2 | 79
cenaknizky1 | 20 Kč
cenaknizky2 | 30 Kč

Potřeboval bych výstup:
ID | NAZEV        | STRANY | CENA
----------------------------------
 1 | První knížka |    250 | 20 Kč
 2 | Druhá knížka |     79 | 30 Kč

Zkoušel jsem něco jako:
SELECT knihy.id, knihy.nazev, knihyvlastnosti.atribut, knihyvlastnosti.hodnota FROM knihy, knihyvlastnosti
WHERE (knihyvlastnosti.atribut = CONCAT('pocetstran', knihy.id ) 
OR text.id = CONCAT('cenaknizky', knihy.id ))

To mi ale vrátí pro každou knihu dva řádky. Není tedy možnost, jak tyto řádky spojit do jednoho, když vždy budu vědět počet atributů v tabulce knihyvlastnosi? Pokud ne, spojím to pak v PHP, kdyby byla ale cesta i v mysql, bylo by to elegantní.

Díky!
pcmanik
Profil
Na spajanie sa pouziva GROUP BY.

Mas zle navrhnutu tu strednu tabulku, malo by to byt neico na sposob:
id_knihy, pocet_stran, cena

Potom ziskas vystup jednoducho
SELECT id, nazev, pocet_stran, cena WHERE id = id_knihy
Tori
Profil
DB mi připadá nevhodně navržená, počet stran a cena jsou vlastnosti buď knihy, nebo konkrétního vydání, patří tedy k němu. Podle toho, jestli chcete rozlišovat různá vydání nebo ne, může být návrh buď:
-- tabulka knihy --
id knihy (int, auto increment, primární klíč)
id autora (int, klíč)
název (varchar)
počet stran (smallint)
cena (smallint) ... případně jazyk, URL obrázku titulní strany atd.
anebo s rozlišením různých vydání:
-- tabulka knihy --
id knihy (int, auto increment, primární klíč)
id autora (int, klíč)
název (varchar)

-- tabulka vydani --
id vydání (int, auto increment, primární klíč)
id knihy (int, klíč)
počet stran (smallint)
cena (smallint) ... případně jazyk, URL obrázku titulní strany atd.
Něco o normalizaci DB si můžete přečíst např. na manualy.net.
regy
Profil
pcmanik:
Díky, group by znám, ale nevím jak to spojit, aby mi nevypadla jedna z hodnot.

pcmanik, Tori:
Je to modelový příklad, v původním návrhu tato databáze smysl má. Díky za snahu, ptal jsem se jak získat požadovaný výsledek z těchto tabulek a ne jak přenavrhnout databázi ;-).
Tori
Profil
regy:
v původním návrhu tato databáze smysl má
Ale aspoň by se měly oddělit název vlastnosti a ID knihy do dvou sloupců, takhle si komplikujete SQL dotazy i zpracování výsledků.
Pokud tedy takto, tak bych nepoužila GROUP BY, ale jen ORDER BY knihy.id a zpracovala to až v PHP. Buď jedním dotazem načíst vše, anebo prvním dotazem jen data z tabulky knihy a druhým dohledat vlastnosti podle ID. Koukněte se na článek Srovnání dotazů do závislých tabulek.
edit: Jsem ten předchozí příspěvek napsala asi příliš kategoricky, tak pardon.
regy
Profil
Tori:
Přesně nad tím, zda jsem neměl už na začátku rozdělit jakýsi prefix a id dané skupiny parametrů, jsem se po Tvojí reakci také zmyslel. Vzhledem k tomu, že do databáze míří ale většinou dotaz na konkrétní záznam a ne třeba jen na všechny LIKE "pocetstran%", asi to nevadí. Používám tuto tabulku v celém systému na veškeré texty, které jsou multijazykové. Použil jsme jednu tabulku na všechny překládané texty hlavně kvůli budoucímu návrhu vyhledávání, které skoro na všech webech, které jsi ho řeší sami, nehledá ve všech částech webu, ale třeba jen v článcích apod. To, jestli to bylo šťastné řešení po čase nakonec zjistím sám. Pro menší weby do stovek článků nebo různých stránek (což je většina zakázek) je toto řešení elegantní a rs nemusí mít sto tabulek, jako některé redakční systémy.
Děkuju za článek. Myslím, že dotazy ze začátku podceňuje hodně lidí. Já na to také přišel až u webu se 100MB databázemi :-).
edit: Mou předchozí odpověď jsem zase já napsal příliš arogantně a povýšeně. Omlouvám se dámě ;-).
nototo
Profil *
SELECT knihy.id,
       knihy.nazev,
       strany,
       cena
FROM   knihy
       JOIN (SELECT REPLACE(atribut, 'pocetstran', '') AS id,
                    hodnota                            AS strany
             FROM   knihyvlastnosti) AS temp1
         ON temp1.id = knihy.id
       JOIN (SELECT REPLACE(atribut, 'cenaknizky', '') AS id,
                    hodnota                            AS cena
             FROM   knihyvlastnosti) AS temp2
         ON temp2.id = knihy.id
WHERE  knihy.id = 1  

zkus tohle .. vypadá to hrozně, ale mohlo by to fungovat :)
regy
Profil
nototo:
Děkuju, funguje. Když jsem ale viděl, že i bez dat to trvá 4x déle než dotaz vracející 2 řádky pro jeden záznam, asi to ošetřím v php. Ale děkuju za rošíření obzorů!
Kajman
Profil
regy:

Ale o tom je to přesvědčování v celém vlákně. Když budete mít ten primární klíč jako kombinaci těch dvou sloupců nesplácnutých do sebe, tak budete mít aplikaci svižnější.
regy
Profil
Kajman:
Jo jo, máte pravdu, zase mi to pak ale zesložití dotazy na všech ostatních místech. Tušení, že ať zvolím tak, či onak, později by se mi více hodila druhá varianta, ve mě zároveň ale vyvolává tendence nechat to tak, jak to je. Každopádně děkuju všem za náměty, stále je co zlepšovat ;-). Dá se tedy říct, že zabere hodně času příkaz replace oproti contact?
Díky
Kajman
Profil
regy:
ale zesložití dotazy na všech ostatních místech

Kdepak, oprava je na chviličku, žádné složitosti nejsou potřeba (oproti tomuto hrůznému řešení ;)
Tori
Profil
regy:
V nějakých jiných tabulkách máte taky uložené jako cizí klíč ten složený zápis "atributID"?
regy
Profil
Kajman:
No ale na tabulku jsou napojeny i všechny ostatní dotazy, které hledají nějaký text pro vypsání a pro ty je tento návrh akorát, protže vždy hledají konkrétní záznam (podmínka je tedy vždy atribut = "neco$promenna"). Až teď jsem narazil. Zkusil jsem smazat replace a přidat contact do podmínky, ale rychlost je pořád stejná :-(.
Edit: běží mi na tom celý redakční systém, teď dělám jen modul pro katalog produktů


Tori:
V jiných tabulkách ne, jen v téhle, ale dotazuje se na to ze spoustu míst, kde bych to musel opravovat jen kvůli jendomu modulu. Ale asi jste mě všichni udolali. Asi to má smysl.
nototo
Profil *
Smysl to určitě má. Potom se vyhneš přesně takovýhmle šílenostem a hrůzným řešením, které Ti teď vznikají díky špatnému návrhu struktury databáze.
regy
Profil
nototo:
Uvidíme. Změnu jsem provedl, ale zatím se změna projevila jen tak, že se mi zvětšil index :-).

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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