Autor Zpráva
arnoost
Profil
Omlouvam se pokud už o tom někdo psal. Omlouvam se zda to melo byt do SQL.

Stale dokola stejný problém. Priklad:

Tabulka s komentari.

ID komentID PRODID nazev popis datum
1 0 pr1 aaa bbb
2 1 pr1 ccc ddd

Komentáre jsou propojeny pres komentID a já bych chtěl na jeden dotaz do SQL vybrat komentáre (to bych asi zvládl) a následně je vypsat v php tak aby byli komentáre s odpověďmi pod sebou.

komentar
-- odpoved 1
-- odpoved 2
-- odpoved 2

komentar 2
-- odpoved 1
-- odpoved 2
atd.

řešení while {
while { ... }
}

fakt nechci... Poradí mi někdo.
AM_
Profil
Nejsem si jistý, jestli dobře chápu, co chceš. Tvoříš stromovou strukturu komentářů, nebo existují jen 2 úrovně (komentář a odpovědi na něj)? Ve druhém případě bych to rozhodil do dvou tabulek - komentáře a odpovědi. Ten první případ efektivně řešit neumím.
Alphard
Profil
Proč si nenavrhnete lepší strukturu tabulky? Stromová data spojená jen pomocí ParentID (identifikátor na rodiče) se vypisují rekurzivě, s tím se nic moc nevymyslí. Je-li možné návrh tabulky změnit, dám vám sem odkaz na řešení.
joe
Profil
Alphard
Dej odkaz :-)

arnoost
Nevidím na tom nic špatnýho. Jedním selectem vybereš komentáře i s odpověďma u produktu:
SELECT * FROM comments WHERE PRODID = 'pr1'

A pak si v PHP uložíš jejich stromovou strukturu. Zdá se mi to jako dobré řešení...
Alphard
Profil
joe:
Nevidím na tom nic špatnýho. Jedním selectem vybereš komentáře i s odpověďma u produktu:
SELECT * FROM comments WHERE PRODID = 'pr1'
A to stejné bude muset udělat pro všechny ostatní, jestli umožní zanoření, půjde to do desítek dotazů na db.

Dej odkaz :-)
No jo, nechtělo se mi to hledat. :-)
Teorie – zajímá nás Traverzování kolem stromu (na konci)
Praxe
Trochu náročnější editace
Nápadité odsazování rozsáhlých diskusí
joe
Profil
Alphard
A to stejné bude muset udělat pro všechny ostatní, jestli umožní zanoření, půjde to do desítek dotazů na db.
Proč proboha? :-) Jestli chápu jeho strukturu databáze, tak ne, tak mu stačí k vypsání komentářů (i zanořených) k jednomu produktu právě jedním dotazem - tím jednoduchým selectem, co jsem poslal.

Když vezmu v úvahu, že je vše v jedné tabulce (pokud to tak není - udělal bych to tak ;-)), tak u komentářů a komentářů, které mají rodiče je vždycky uvedeno ID produktu, ke kterému patří - proto vyberu jen ty, které patří k danému produktu v PHP setřídím. Zdá se mi to jako nejmenší zátěž na db.

Díky za odkazy.
arnoost
Profil
To joe: Ano je to tak jak jsi to popsal.. jen nevim to řazení v php.. Ale nějak to nastuuji... Je to vážne jen jednoducha tabulka a komentare jsou vzdy k jedne položce... Neni to nic složitého jako nejake traverzování či něco podobného....

Jde jen o seřazení:

koment
odpovedi

koment 2
odpovědi 2
Alphard
Profil
Čekám na řešní od joe, protože to setřízení mi nepřipadá až tak jednoduché.
Máme nijak nesetříděnou sadu záznamů a co teď?
sort() apod. těžko, není podle čeho třídit, id i datum je k ničemu, komentID také nebude ideální (rodičovské prvky budou s nulou někde na začátku), takže se to bude muset ošetřit.

Já bych změnil návrh tabulky. Když nechcete kompletní strom, tak aspoň ta část "Rozšíření ploché tabulky" z dříve odkazované teorie. Je to jednoduché a přehledné.
arnoost
Profil
A jak by to melo byt správně.? Tedy tabulka a pripadne dotaz...
stejný problem je kategorie a podkategorie
produkt a podprodukt

Všechno je stále dokola a mě to všechno příjde nějak moc složité.
Děkuji.
AM_
Profil
arnoost
Škoda, žes neodpověděl na můj dotaz, zda tvoříš stromovou strukturu, nebo jen 2 úrovně (komentář a odpověď, kategorie a podkategorie) - tj polopatě jestli může existovat "podpodkategorie" atd... To je na tom to zásadní.
arnoost
Profil
Omlouvám se zda jsem na něco neodpověděl. Není to zádna zasadní struktura.
Vse jen dvě urovně... Kategorie - podkategorie
Komentář - odpověd
Produkt - podprodukt
Alphard
Profil
arnoost:
a je to :-) AM_ vám teď poradí 2 tabulky, joe třizení v PHP a já jen zopakuji, že s vhodnou strukturou stačí
 $result = mysql_query('select * from tabuka order by ord asc'); 
  while ($row = mysql_fetch_array($result))
  { 
     echo str_repeat(" ",$row['LEVEL']).$row['NAME']; 
  }
AM_
Profil
Tak to to ujasňuje, pak si data rozděl:
CREATE TABLE kategorie(
  jmeno VARCHAR(100),
  ...
  id INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY(id)
)
CREATE TABLE podkategorie(
  jmeno VARCHAR(100),
  ...
  rodic INT NOT NULL,
  id INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY(id)
)

a vybírej přes
SELECT kategorie.jmeno as katjmeno, podkategorie.jmeno as podjmeno, ... FROM kategorie LEFT JOIN podkategorie ON kategorie.id = podkategorie.rodic

a podobně s komentáři.
AM_
Profil
Alphard
pěkná předpověď :) samozřejmě, jde to mít i v jedné tabulce, ale s ohledem na strukturu dat mi takhle přijde pravděpodobně lepší to rozdělit. Pravděpodobně říkám, protože to závisí na přesné struktuře webu, jak moc se entita kategorie liší od podkategorie.
arnoost
Profil
Děkuji za odpovědi. Asi to musí byt boj vysvětlovat něco někomu kdo tomu očividně nerozumí :) U komentářů budu muset asi ukladat level.
Dvě tabulky pro kategorie jsou asi fajn ale já bych se zase zasekl na vkladání kategorií a podkategorii. Takhle to mohu vkladat do jediné tabulky.. Musí to byt simple a fast. Ještě jednou děkuji.
joe
Profil
Alphard
Čekám na řešní od joe, protože to setřízení mi nepřipadá až tak jednoduché.
:-) Mně se to moc složité nezdá, ale chce to si chvilku nad tim sednout a zamyslet se nad tím, ale tak když už jste tu vymysleli řešení, tak vám ho nebudu znepříjemňovat. Napíšu jen jak bych na to šel, teď teda doufám, že ve sloupci komentId je vlastně parent kam komentář patří.
Jednoduše bych vybral všechny komentáře k produktu s daným id a pak přes nějaký for/while ukládal do pole asi takhle

Pro znázornění
array( 
"komentář" => array(...,  "odpovědi" => array(...) ),
"komentář" => array(...,  "odpovědi" => null ),
"komentář" => array(...,  "odpovědi" => array(...) ),
)

Myslím, že by to mělo jít a neměl by v tom být problém :-)
arnoost
Profil
Ještě tedy rada pro příště... Jak by to mělo správně vypadat z hlediska DB a PHP. Podobné návody jsem nikde na netu nenašel.
Třeba ty komentáře: tak aby to byla jedna tabulka. Koment - odpoved. A dalo se to nejak jednoduse s formatovat ve while nebo tak neco?
joe
Profil
arnoost
Pokud to máš uložené v jakémkoli "formátu", který uznáš za vhodné, pak si to můžeš zformátovat jak chceš.

Pokud předpokládám třeba v $result to pole co jsem psal, pak jednoduše můžeš komentáře vypsat.
<?php

foreach($result as $comment) {
echo $comment['...'];
if($comment['odpovědi'] !== null) {
// tady bude výpis odpovědi ke komentáři...
}
}
Alphard
Profil
arnoost:
V podstatě ti odpověděl joe, jakmile máš jednotlivé komentáře v setřízeném poli, tak se snadno naformátují do jakékoliv podoby.
Na netu je dost návodu, mnoho z nich je v angličtině. Ale co jsem četl, tak žádný z nich nepřináší žádnou revoluci. Odkazovaný článek na intervalu docela dobře shrnuje možnosti. Nejsou tam ukázky, jak řešit přesuny uzlů, mazání apod. ale to lze najít jinde.
Vše vždy vychází z toho, co chceme zjednodušit a co si dovolíme zkomplikovat. Metoda ParentID, v podstatě to vaše, je triviální na představu a údržbu, ale výpis se řeší buď rekurzivně, nebo, pokud jde jen o dvě úrovně, jak ukázal joe, což je samozřejmě neefektivní. Ale většinou se vychází z toho, že se data až tak často needitují, ale často vypisují, a proto správa tabulky je sice složitá, ale vypsat se dá vše jednoduchým cyklem.

joe:
Ano, takové řešení mě napadlo, je docela známé i na jiné věci. Ale beru to z pohledu efektivity. Dotaz na databázi je vždy jeden, takže můžeme zanedbat. Setřízení (samozřejmě s indexem na ord) je pro databázi prkotina. Oproti tomu vaše řešení vezme výsledky z databáze a začne tvořit nové pole, to ukládá do paměti a až poté ho vypíše. Samozřejmě záleží na datech. Pro deset komentářů je to zanedbatelné, ale pro stovky už má smysl o tom uvažovat. A to ani nemluvím o stránkování, těžko budete stránkovat něco, kde je odpověť na konci, otázka na začátku a navíc nemáme podle čeho řadit. A navíc, pokud časem dojte k rozšíření na více úrovní, tak to není problém.
arnoost
Profil
Ok. Diky za rady. Vidím, že způsobuje je hromada. Jak moc je tohle neefektivní? Bude na řádově desítky záznamů.

<?php
       $sqlCommnet ="SELECT DISTINCT $pref_comment.com_id AS com_id, $pref_comment.pro_id, $pref_comment.nazev AS comnazev, $pref_comment.text, DATE_FORMAT($pref_comment.datum, '%d.%m.%Y - %H:%i') as datum, $pref_comment.kom_id AS parentID
       FROM $pref_comment
	      LEFT JOIN $pref_comment AS recom ON recom.kom_id = $pref_comment.com_id
	      WHERE $pref_comment.pro_id = '$prodID' ORDER BY $pref_comment.com_id ASC
	      ";
       $sqlCom = mysql_query($sqlCommnet);	      
       while ($row = mysql_fetch_assoc($sqlCom)) {
       if($row['parentID'] == '0') { ?>
	      <hr size="1" />
	      <div class="comtit">
		 <b><?php echo $row['comnazev']; ?> </b> | <?php echo $row['datum']; ?> | <a href="comment-odpoved.php?product=<?php echo $prodID;?>&amp;odpoved=<?php echo $row['com_id']?>">Odpovědět</a>
		 <p><?php echo nl2br($row['text']); ?></p>
		 <br />
	      </div>
       <?php } else { ?>
              <div class="comm">
		     <b><?php echo $row['comnazev']; ?></b> | <?php echo $row['datum']; ?>
		     <p><?php echo nl2br($row['text']); ?></p>
              </div>
       
       <?php }
       }
       mysql_free_result($sqlCom);
?>

Moderátor Alphard: Snažím se poupravit ukázku tak, aby to neházelo jush error a spráně obarvilo.
joe
Profil
Alphard
Nepochybuju o tom, že to řešení výš je daleko lepší. Šel jsem na to jednoduše a logicky, navíc když jsem viděl co všechno jde do proměnných nacpat, tak se toho nebojím.
Najsem žádný expert... v nějakých oblastech spíš naopak a nevykejte mi všichni :-)
Alphard
Profil
arnoost
Myslím, že na desítky záznamů bez problémů. Ten dotaz bych asi stavěl jinak, možná i poddotazem vytáhnout jen rodiče (parentID = 0) a pro správný produkt a až na to s left join reakce. Nakonec by asi ani nebyl potřeba distinct, ale jenom čert nebo Kajman ví, co je rychlejší :-)

joe
Jasně, psal jsem to jako reakci na tebe, ale bylo to myšleno pro celou diskusi. A pokud jde o vykání, to mě naučil Kajman, když jsem, svého času, vyjádřeno poměrem na celou diskusi, trávil podstatnou část času v databázích (předtím jsem tykal všem). Teď jsem snažím aspoň pravidelným přispěvatelům tykat, ale občas zapomenu.

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: