Avatar billede MissVinter Novice
21. april 2010 - 19:42 Der er 19 kommentarer og
1 løsning

Vis kun 1 enhed ved brug af joins - PHP og MYSQL

Hej
Jeg er lidt af en nybegynder, hvad angår php og mysql.
Jeg sidder og roder med en gæstebog. Ideen er, at en bruger skal kunne skrive et indslag, hvorefter andre brugere kan kommentere på dette indslag.
Problemet: Hvis der er flere kommentarer til et indslag, dukker indslaget op igen, hver gang en ny kommentar kommer. Jeg vil gerne lave en kode, hvor selve beskeden kun kommer én gang, hvorefter kommentarerne kommer direkte efter hinanden herefter. Jeg har rodet lidt med GROUP BY og DISTINCT, men det er vist ikke her jeg finder løsningen??? SNØFT..

Min (prototype)kode er her:

$result = mysql_query("
SELECT forfatter, indslag, kommentator, kommentar from Table1 LEFT JOIN Table2 ON Table1.indslagid = table2.indslagid;
");

while ($row = mysql_fetch_array($result)){
echo "
$row[0]
$row[1]
$row[2]
$row[3]
";}

Håber det giver mening, lidt svært at forklare…
Avatar billede Slettet bruger
21. april 2010 - 20:12 #1
Generelt er det ikke det mest optimale sted at bruge JOINS.
Når du gør dom du gør, så får du indslagets-data med for hver kommentar hvilket du jo ikke ønsker.
Så hvis jeg var dig ville jeg bare starte med at hente indslaget i én forspørgelse og så bagefter henter alle kommentarer i en anden forspørgelse og så loope resultaterne igennem.
Avatar billede MissVinter Novice
21. april 2010 - 21:18 #2
Mange tak for det hurtige svar roxki, men pyh er noget forvirret.

Jeg har forsøgt at lave to forespørgsler og lagt den sidste while-loop ind i den første. Men så kommer alle kommentarerne efter det første indslag?
Jeg bliver vel nødt til at lave en join i forespørgsel 2?
Jeg er vist lidt ude på dybt vand. Har du et eksempel på, hvad jeg kunne gøre i denne situation?

Min nye kode kommer her - ved ikke om det er helt skørt:

$result = mysql_query("
SELECT forfatter, indslag from table1;
");

$result2 = mysql_query("
SELECT kommentator, kommentar from table1 LEFT JOIN Table2 ON Table1.indslagid = Table2.indslagid;
");

while ($row = mysql_fetch_array($result)){
echo "$row[0]
$row[1]
<br/>
";

while ($row = mysql_fetch_array($result2)){
echo "$row[0]
$row[1]
<br/>
";
}

}
Avatar billede Slettet bruger
21. april 2010 - 22:09 #3
Du bliver nød til at starte med at hente dit indslag.
Når du har hentet det kan du så via indslagets ID hente tilhørende kommentarer.
Et MEGET simpelt eksempel kunne se således ud:
<?php
// Henter alle indslag
$indslag_result = mysql_query("SELECT `id`, `forfatter`, `indslag` FROM `table1`");

// Looper indslagene igennem
while($indslag_data = mysql_fetch_assoc($indslag_result)) {
  echo '"' . $indslag_data['indslag'] . '"<br><br>Indslag skrevet af ' . $indslag_data['forfatter'] . '<br>';

  // Nu vil vi gerne hente alle kommentarer til dette indslag
  $kommentar_result = mysql_query("SELECT `kommentator`, `kommentar` FROM `table2` WHERE `indslagid` = " . $indslag_data['id']);
  // Looper igennem kommentarene
  while($kommentar_data = mysql_fetch_assoc($kommentar_result)) {
    echo '"' . $kommentar_data['kommentar'] . '"<br><br>Kommentar skrevet af ' . $kommentar_data['kommentator'] . '<br>';
  }
  echo '<br>';
}
?>

Du skulle nu gerne få et output der vil være noget ala. dette:
"Dette er et indslag"

Indslag skrevet af roxki

"Jamen det er det da"

Kommentar skrevet af roxki


Opsætningen er lidt forvirrende, men håber du forstår hvad der sker!
21. april 2010 - 22:09 #4
God aften og velkommen paa Eksperten.

Maa jeg spoerge hvad du har staaende i tabel1 og i tabel2?  Det ville vaere logisk hvis du placerede de oprindelige indslag i tabel 1 med indslagid, forfatter, og indslag og placerede kommentarer i tabel2 med kommentarid, indslagid, kommentator, og kommentar i tabel2.

Saa vil jeg i oevrigt foreslaa at du skaelner mellem hvad resultatet af din query er og hvordan du skriver den ud.  Med den tabelstruktur jeg har skitseret vil jeg foreslaa en kode noget i den henretning:

$indslag = 0;
$result = mysql_query("SELECT tabel1.indslagid, forfatter, indslag, kommentator, kommentar FROM tabel1 LEFT JOIN tabel2 ON tabel1.indslagid = tabel2.indslagid ORDER BY tabel1.indslagid");
while($row = mysql_fetch_array($result))
{
  if($row[0]) != $indslag
  {
    $indslag = $row[0];
    echo $row[1] . "<br/>";
    echo $row[2] . "<br/>";
  }
  echo $row[3] . "<br/>";
  echo $row[4] . "<br/>":
}

Altsaa, hvis et indlaeg har ti kommentarer saa leverer din query inlaegget ti gange, men du echoer det kun foerste gang.

Jeg har ikke testet det, men det svarer til loesninger paa andre tilsvarende spoergsmaal.
21. april 2010 - 22:13 #5
Der kolliderede jeg omtrent med roxki.  roxki foreslaar en loesning med to database forespoergsler.  Med al respekt saa mener jeg at min loesning er enklere, du henter det hele paa en gang fra databasen og saa lader du php-koden sortere det ud.  Men det er maaske som man tager det.
Avatar billede Slettet bruger
21. april 2010 - 22:37 #6
Ved at hente indslag og tilhørende kommentarer, vil man hente mere data fra databasen i det at selve indslagets data vil blive sendt for hver kommentar der er skrevet.
Men som sagt det er smag og behag, personlig syntes jeg det er spild at hente indslagets data igen og igen for hver kommentar når det alligevel kun bruges én gang.
Avatar billede MissVinter Novice
21. april 2010 - 22:43 #7
Mange tak for hjælpen roxki og Christian_Belgien.

Det ser helt sikkert ud, som noget jeg kan bruge, men tror lige jeg vil lade det vente til den store test imorgen, hvor jeg har friske øjne ;)

Til Cristian_Belgien, Ja mine tabeller ligner det, du anbefaler. Du kan se dem sidst i denne besked.

Fortsat god aften :)


CREATE TABLE table1 (
indslagid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
forfatter varchar(50),
indslag text
)ENGINE=InnoDB;

CREATE TABLE table2 (
kommentarid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
indslagid INT NOT NULL,
kommentator varchar(100),
kommentar text,
FOREIGN KEY (indslagid) REFERENCES table1(indslagid)
) ENGINE=InnoDB;
Avatar billede limemedia Nybegynder
22. april 2010 - 07:09 #8
roxki har ret i denne situation, two select forespoergsler til databasen er meget hurtigere end at bruge en join

men du burde have tre tabeller, hvor forfatter fra table1 ligges i en seperat tabel, saa du ender med en lignende struktur

tabel indslag
- indslag_id (medium int, unsigned, primary key, auto_increment)
- forfatter_id (small int, unsigned)
- indslag (text)
- tid (datetime)

tabel kommentar
- kommentar_id (medium int, unsigned, primary key, auto_increment)
- indslag_id (medium int, unsigned)
- forfatter_id (small int, unsigned)
- kommentar (text)
- tid (datetime)

tabel forfatter
- forfatter_id (small int, unsigned, primary key, auto_increment)
- forfatter (varchar)
- andre attributter du vil knytte til en forfatter, profil, email, kontakt osv

og saa koere SQL-en som

SELECT i.indslag, i.tid, f.forfatter
FROM indslag AS i, forfatter AS f
WHERE i.forfatter_id=f.forfatter_id
ORDER BY i.tid DESC

og

SELECT k.kommentar, k.tid, f.forfatter
FROM kommentar AS k, forfatter AS f
WHERE k.forfatter_id=f.forfatter_id
ORDER BY k.tid DESC

saa du paa den maade faar et mest muligt fleksibelt system
Avatar billede limemedia Nybegynder
22. april 2010 - 07:10 #9
hov, den anden SQL skulle vaere

SELECT k.kommentar, k.tid, f.forfatter
FROM kommentar AS k, forfatter AS f
WHERE k.forfatter_id=f.forfatter_id && k.indslag_id="1"
ORDER BY k.tid DESC

hvor 1 er indslag_id'et fra foerste kald
Avatar billede MissVinter Novice
22. april 2010 - 11:36 #10
Ej hvor var det cool. Det eksempel, du gav mig Roxki, udførte lige præcis det, jeg havde brug for :)

Jeg kan sagtens se, at der er god mening i at have tre tabeller, som du anbefaler Limemedia. Men regner ikke med, at der kommer til at ligge vanvittigt meget data i min gæstebog, så i denne omgang klarer jeg den med to tabeller..

Hvor er det fedt, at I gad og hjælpe mig allesammen. Pyh, jeg kunne have brugt evigheder på at skulle komme frem til det selv.
Endnu en gang mange tak til jer alle :)
Avatar billede MissVinter Novice
22. april 2010 - 14:24 #11
Nå så opstod det næste problem. Ved ikke om der stadigt skulle være nogen, der er friske på at finde en fejl??

Nye kommentarer skal jo stå i forbindelse med det rette indslag.  Jeg forsøger at sende indslagid med, når jeg sender mine data til det dokument (gem_kommentar.php), hvorfra de nye data indsættes i databasen. Men der sker intet. Jeg har i gem_kommentar.php-dokumentet en 'header Location', der dirigerer brugeren tilbage til forsiden, men man kommer ikke videre fra gem_kommentar.php, og de nye data bliver ikke indsat i tabellen Table2. Jeg kan simpelthen ikke forstå, hvor fejlen er??? Min kode kommer her:

// Henter alle indslag
$indslag_result = mysql_query("SELECT `indslagid`, `forfatter`, `indslag` FROM `Table1`");

// Looper indslagene igennem
while($row_indslag = mysql_fetch_assoc($indslag_result)) {
  echo '"' . $row_ indslag ['indslag'] . '"<br>Indslag skrevet af ' . $row_indslag ['forfatter'] . '<br><br>';

// Nu vil vi gerne hente alle kommentarer til dette indslag
  $kommentar_result = mysql_query("SELECT `kommentator`, `kommentar` FROM `Table2` WHERE `indslagid` = " . $row_ indslag ['indslagid']);

// Looper igennem kommentarene
  while($row_kommentar = mysql_fetch_assoc($kommentar_result)) {
    echo '"' . $row_kommentar['kommentar'] . '"<br>Kommentar skrevet af ' . $row_kommentar['kommentator'] . '<br><br>';
  }
//Herefter har jeg lavet et kommentar-felt (en form), hvor jeg via et hidden-felt sender indslagid med til gem_kommentar  dokumentet, så kommentaren bliver tilknyttet rette indslag 


$indslagid = $row_indslag['indslagid'];
?>

<form action="gem_kommentar.php" method="post">
<input type="hidden" name="indslagid" value="<?php echo $indslagid;?>"/>
<p>Dit navn: <input type="text" name="kommentator" /> </p>
<p>Tilføj kommentar:<textarea name="kommentar" rows="3" cols="30"></textarea></p>
<input type="submit" value="tilføj" />
</form>
<?php
}

//I gem_kommentar-dokumentet har jeg  koden :
$indslagid=$_REQUEST['indslagid']
$kommentator=$_REQUEST['kommentator'];
$kommentar=$_REQUEST['kommentar'];
mysql_query("INSERT INTO Table2  VALUES ('', '$indslagid','$kommentator', '$kommentar')");



Pyh det var en længere én.... Håber det giver mening
22. april 2010 - 14:51 #12
For god ordens skyld, du oprettede et spoergsmaal og det fik du (adskillige) svar paa, og du indikerer at at du fik svar paa spoergsmaalet.  Saa du boer nu afslutte DENNE traad og give points (som du skoenner ret).  For det naeste problem maa du saa oprette et nyt spoergsmaal.  Det nye spoergsmaal faar saa opmaerksomheden af alle medlemmer af Eksperten, ikke kun de der har vaeret involveret i denne traad.
Avatar billede MissVinter Novice
22. april 2010 - 15:08 #13
Ok Christian_Belgien.
Det er hermed taget til efterretning. Jeg er ny herinde, så er ikke helt fortrolig med normerne herinde. Mit første spørgsmål er helt klart besvaret fint herinde, mange tak for det. Det næste spørgsmål skal jeg nok finde en løsning på :)
Avatar billede michael_stim Ekspert
22. april 2010 - 15:38 #14
Hej MissVinter, og velkommen til eksperten. Kan se at du har problemer med at uddele point. Det du gør er at bede dem der har hjulpet med at løse dit problem, at lægge et svar. Når de så har lagt et svar, accepterer du svaret/svarene på de personer du syndes skal have point. Du behøver altså ikke at oprette et nyt spørgsmål, alt kan gøres i denne tråd ;o)
22. april 2010 - 15:48 #15
Avatar billede Slettet bruger
22. april 2010 - 17:20 #16
For at gøre det lidt nemmere for dig vælger jeg at smide et svar med det samme og så kan du jo give mig points hvis du syntes jeg har fortjent det! :-)
Avatar billede MissVinter Novice
22. april 2010 - 21:24 #17
Hej Christian_Belgien, limemedia og michael_stim

Læg endeligt et svar til mig, så uddeler jeg naturligvis points til jer. Håber jeg gør det rigtigt denne gang, ellers må I jo lige sætte mig på plads igen ;)
Avatar billede MissVinter Novice
22. april 2010 - 21:32 #18
Hej igen roxki.

For ikke at gøre mig yderligere upopulær herinde, kan du så ikke lige fortælle mig, hvor mange point, man typisk vil give f.eks. for den hjælp, du har givet mig?
Der medfølger belønning for dit svar ;)
Avatar billede michael_stim Ekspert
22. april 2010 - 22:05 #19
Spørgsmål angående eksperten er normalt gratis. 30 point er passende for sådan et spørgsmål. Men tror de fleste i bund og grund er mere eller mindre ligeglade med point, man kan jo ikke købe noget for dem. Men ret skal være ret. Når man nu KAN tjene point, så syndes jeg det er op til opretter hvem der skal have dem. Lige i denne tråd, har jeg absolut ikke fortjent nogle point, selv om du bad mig lægge et svar.

Og tror nu ikke der er nogen der bliver sure på dig pga dette her. Så der er nok ingen grund til at blive nervøs for at blive upopulær herinde ;o)
22. april 2010 - 22:11 #20
Nu fik du tildelt de 30 points til roxki der er til raadighed under dette spoergsmaal.  Derved har du lukket det (dets farve er nu groen). 

I mellemtiden har du aabnet et par nye spoergsmaal.  Et af dem er http://www.eksperten.dk/spm/907776#reply_7579248 som hedder Points til Christian.  Det er vigtigt (for mig) at du lukker ogsaa det.  Hvis du mener at jeg har hjulpet dig med dit spoergsmaal saa skal du lukke det ved at acceptere mit svar paa det spoergsmaal (paa samme maade som du nu har accepteret roxki's svar.)  Ellers maa du selv laegge et svar og acceptere det.  Men luk det. Please.

Du fik ogsaa oprettet dette spoergsmaal http://www.eksperten.dk/spm/907756 Points til Roxie.  Som sagerne staar nu maa du selv laegge et svar paa det spoergsmaal (for eksempel blot sige "Lukker") og acceptere det svar.  Saa skulle der vaere ryddet op.

Du er ikke upopulaer (hos mig i det mindste,) men du er forvirret.  Naar du laver dit naeste spoergsmaal saa opret det med det total antal points du vil give, see hvem der loeser dit problem, hvis det medlem har lavet et svar saa accepter det, ellers bed om et svar og accepter det, og tak de oevrige medlemmer der har givet indlaeg.  Hvis to medlemmer har givet substantiel hjaelp er den normale fremgangsmaade at dele points mellem dem ved at acceptere begge's svar.  Hvad angaar antal points for et spoergsmaal som dette saa er der ikke noget forkert med 30 saa laenge du endnu ikke har saa mange at dele ud af.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester