Autor Zpráva
Radicz
Profil *
Dobrý den,

rád bych požádal o pomoc s dotazem do databáze. Mam tabulku tarifů kde mam sloupečky t_boxi, t_cena, t_foto, t_parametry, t_seznam, tyto sloupce obsahují hodnoty jednotlivých id v jiných tabulkách. Tzn t_foto má hodnotu 1,2,3 například a znamená to že, chci vypsat hodnoty které jsou v tabulce t_boxi s id 1,2,3. Je to trochu složité na vysvětlení přiložím tedy obrázek. Stejně myšlené jsou i ostatní zmíněné sloupce. Bohužel netuším jak vypsat všechny řádky s požadovaným ID a zároveň ze všech tabulek.
Alphard
Profil
Chybný návrh databáze. Využijte spojovací tabulky, zřejmě relace M:N.
Kajman_
Profil *
Máte tabulky špatně navržené. Pro vazbu 1:N vytvořte vždy speciální vazební tabulku.

Takže bude tabulka tarify bez sloupce t_boxi.
Nová tabulka tarif_t_boxi (sloupce id_tarif,id_boxi) bude mít tři řádky
1 1
1 2
1 3

Takhle to uděláte pro všechny sloupečky, kde může být k jednomu tarifu více hodnot.

Trocha teorie:
http://www.manualy.net/article.php?articleID=13
Radicz
Profil *
Děkuji za rady, předělam to
Radicz
Profil *
Dobrý den, zase já.

Podle vašich rad jsem udělal jiný návrh databáze. Nyní to mam tak že mam tabulku s tarifem, tabulku která určuje kde se nacházejí hodnoty které chci vypsat v jíné tabulce. Doufám že na pochopení pomůže obrázek. Podařilo se mi složit tento dotaz, který v podstatě dělá to co jsem chtěl aby dělal. (Až na to že nevypisuje jmenoa popis z tabulky tarify_tarify jen jednou). Bohužel si nyní nevim rady jak tento dotaz zkombinovat tak aby stejnou činnost dělal i pro ostatní tabulky. Jako je tarify_foto, tarify_seznam atd. Děkuji za případné rady.

  $query = mysql_query("
                          SELECT tarify_tarify.jmeno As jmeno, tarify_boxi.*
                          FROM tarify_tarify INNER JOIN tarify_prirazeni_boxi 
                          ON tarify_tarify.id_tarif = tarify_prirazeni_boxi.id_tarif
                          INNER JOIN tarify_boxi
                          ON tarify_prirazeni_boxi.prirazeni = tarify_boxi.id_boxi
                      ");

  while($radek = mysql_fetch_array($query))
  {
    echo $radek['nadpis']."<br>";
    echo $radek['hodnota']."<br>";
    echo $radek['doplnek']."<br>";
    echo $radek['jmeno']; 
  }
Alphard
Profil
Pro připojení dalších tabulek přidejte další join.

Až na to že nevypisuje jmenoa popis z tabulky tarify_tarify jen jednou
Vypisují se všechny kombinace řádků, které splňují dané podmínky. Pak se získaná sada upravuje při výpisu.
Už si nevzpomínám na ten váš první obrázek, ale přemýšlím, jestli by vám bývalo nestačilo více dotazů s konstrukcí where id in(…). Ale asi ne, když Kajman souhlasil :-)
Radicz
Profil *
No právě, tady nastává ta potíž, nejsem schopen ten dotaz obohatit o další JOIN aby byl funkční, zkoušel jsem to dnes celé odpoledne. A když už se mi povedlo to zvýšit o jeden JOIN pro další tabulku, dotaz nefungoval tak jak měl. :(
Alphard
Profil
Jak má vypadat výsledek? Můžete prosím dát nějaký stručný příklad?
Radicz
Profil *
Velmi rád, Z první tabulky tarify_tarify vemu jmeno a popis, z tabulky tarify_boxi vezvu řádky který náleží prvnímu tarifu a tak je to se všema ostatníma tabulkama. Takže po kliknutí na odkaz prvního tarifu se vypíše

(tarify_tarify) (tarity_seznam) (tarify_boxi) (tarify_tarify) (tarify_parametry) (tarify_foto)
Název tarifu, 1 až n položka seznamu, 1 až n položka boxu, popis, 1 až n položka parametru, 1 až n položka fotky.

Hlavní myšlenkou je abych si do databáze nastrkal linky na fotografie, nebo různé parametry, atd. A mohl je přiřadit jakémukoliv tarifu.

Takže v parametrech budu mít 10 různých parametrů ale tarifu s ID 1 zobrazim třeba 1, 4, 6 parametr. Stejně tak i fotografie, a další. Zkrátka jakémukoliv tarifu zobrazit cokoliv a nebo také vůbec nic. Děkuji že mi pomáháte to řešit.
Alphard
Profil
Zdá se mi, že [#2] nebyla nejšťatnější rada (relativně, z hlediska správnosti návrhu a normalizace je to teď správně).

Název tarifu, 1 až n položka seznamu, 1 až n položka boxu, popis, 1 až n položka parametru, 1 až n položka fotky.
Tohle se týká výpisu jednoho konkrétního tarifu, nebo seznamu všech?
Radicz
Profil *

„Název tarifu, 1 až n položka seznamu, 1 až n položka boxu, popis, 1 až n položka parametru, 1 až n položka fotky.“
Tohle se týká výpisu jednoho konkrétního tarifu, nebo seznamu všech?


Nevím jestli teď chápu správně Vaší otázku, Jedná se o jeden tarif, ale tyto části bude mít uplně každý tarif. Takže každý z n tarifů se bude skládat z těchto částí -> Název tarifu, 1 až n položka seznamu, 1 až n položka boxu, popis, 1 až n položka parametru, 1 až n položka fotky
joe
Profil
Kajman:
Pro vazbu 1:N vytvořte vždy speciální vazební tabulku.

Nemělo tam být spíš M:N?

Pro vazbu 1:N je zbytečné dělat další tabulku, ne?
Alphard
Profil
Možná se mýlím, ale zdá se mi, že ve vašem případě není spojení ideální řešení. Výsledná data by se začala kombinovat do obrovských rozměrů. Zkusil bych jít cestou většího počtu jednoduchých dotazů.

Hodím sem nástřel, co se mi honí hlavou, ale počkejte si na další názory (nebo můj nový, až se vyspím) :-)

Předpokládám následující strukturu:
tabulka - centrální
externi1, externi2, externi3 - např. vaše tarify_boxi, tarify_foto, …
spojovaci1-3 - asi jasné, pro spojení

select t.*, group_concat(distinct s1.id_ex) ex1, group_concat(distinct s2.id_ex) ex2, group_concat(distinct s3.id_ex) ex3
 from tabulka t
 left join spojovaci1 s1 on t.id = s1.id_tarif
 left join spojovaci2 s2 on t.id = s2.id_tarif
 left join spojovaci3 s3 on t.id = s3.id_tarif
 group by t.id
 where t.id = 3

A ze získaných dat pak vytáhnout vše ostatní:
select * from externi1 where id in (ex1)
select * from externi2 where id in (ex2)
select * from externi3 where id in (ex3)
Kajman_
Profil *
joe:
Nemělo tam být spíš M:N?
Mělo, pardon.

Alphard:
Jedno veliké spojení může být problém a optimální to nebude. To už by bylo lepší něco jako tabulka left join (select group_concat()) left join (select group_concat()) left join ... Na ty selecty s group_concat by mohly být nachystané view, aby to bylo čitelnější (a mysql někdy s view líp optimalizuje plán).

Nebo možná bude lepší udělat více dotazů bez groupování.

select na tarify
select na boxi, co patri k vybranym tarifum
select na parametry, co patri k vybranym tarifum
select na fotky, co patri k vybranym tarifum
select na cosi4, co patri k vybranym tarifum
select na cosi5, co patri k vybranym tarifum

A postupně si to vše chystat do pole v php a z toho to pak vypsat. Když by pole bylo problém, tak těch pět dotazů by šlo spojit přes union a když se to seřadí tak, aby byly za sebou tak, jak budou potřebovat, tak se pro výpis může kombinovat čtení z dotazu na tarify a z toho joinu.

Jinak si myslím, že návrh není horší než předtím :-)
Radicz
Profil *
Alphard

To vypadá dost složitě, musim si o tom něco přečíst jak to vůbec bude fungovat. Děkuji.

Kajman_

Pane Kajman o rozdělení na 5 jednoduchých dotazů jsem už uvažoval také. Ale říkal jsem si že 5 dotazů do databáze je celkem dost a pochyboval jsem o rychlosti zobrazení. Ale popravdě sem nevěděl jestli 5 dotazů je špatné nebo dobré. Ke každému dotazu by musela přijít i smyčka atd. Připadalo mi to jako špatný způsob. Jestli to je ale nevim.
Kajman_
Profil *
pochyboval jsem o rychlosti zobrazení

Změřte si rychlost pro různé varianty. Ono někdy i závisí na tom jaké počty řádků z jednotlivých tabulek se budou tahat - podle toho se mohou optimální dotazy lišit.

Těch více dotazů (ale konstantní počet) může dopadnou nejlépe. Bude to podobné jak tu
http://php.vrana.cz/srovnani-dotazu-do-zavislych-tabulek.php
jen těch vazebních tabulek máte pět.
Kcko
Profil
Kajman:
Trocha teorie:
http://www.manualy.net/article.php?articleID=13


Zavirovaná stránka.
Radicz
Profil *
Tak bych moc rád poděkoval, všem kteří se podíleli na vyřešení mého problému. Nakonec jsem použil group_concat jak mi radil pan Alphard. Dotaz pak sice trochu narostl ale zase to plní takový účel jaký má. Děkuji.

Kdyby někdo narazil na stejný problém zde je vzorek:
$result = mysql_query
    ("
      SELECT tarify_tarify.url_jmeno AS jmeno, GROUP_CONCAT(distinct tarify_foto.link) AS foto, GROUP_CONCAT(distinct tarify_seznam.polozka) AS seznam, GROUP_CONCAT(distinct tarify_parametry.polozka) AS parametry 
      FROM tarify_tarify
      LEFT JOIN tarify_zarazeni_foto ON tarify_tarify.id_tarif = tarify_zarazeni_foto.id_tarif
      LEFT JOIN tarify_foto ON tarify_zarazeni_foto.prirazeni = tarify_foto.id_foto
      LEFT JOIN tarify_zarazeni_seznam ON tarify_tarify.id_tarif = tarify_zarazeni_seznam.id_tarif
      LEFT JOIN tarify_seznam ON tarify_zarazeni_seznam.prirazeni = tarify_seznam.id_seznam
      LEFT JOIN tarify_zarazeni_parametry ON tarify_tarify.id_tarif = tarify_zarazeni_parametry.id_tarif
      LEFT JOIN tarify_parametry ON tarify_zarazeni_parametry.prirazeni = tarify_parametry.id_parametry
      GROUP BY tarify_tarify.id
    ");

    $row = mysql_fetch_assoc($result); 
         
    print_r($row["seznam"]."<br>");
    print_r($row["foto"]."<br>");
    print_r($row["parametry"]."<br>");
        

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:

0