Avatar billede Slettet bruger
04. september 2004 - 13:18 Der er 22 kommentarer og
1 løsning

Sortering af array

Jeg har følgende funktion, hvor jeg trækker oplysninger ud til en topscore-tabel.

function maal($data)
  {
    if ($data == "maal")
      {
        aabn_sql_og_vaelg_db();

        $sql = ("SELECT * FROM b91_maal, b91_medlemmer
                WHERE b91_maal.spillernr = b91_medlemmer.spillernr");

        $query_maal = mysql_query($sql) or die (mysql_error());

        if (mysql_num_rows($query_maal) < 1 )
          {
            $border = 0;
            // Ingen maalscorer registreret //
          }
        else
          {
            $border = 1;

            while ($row_maal = mysql_fetch_assoc($query_maal))
              {
                $antal      = $row_maal[antal];
                $navn        = $row_maal[navn];

                $maal[$navn] = ($maal[$navn] + $antal);
              }

            arsort ($maal);

            $i_liste = 1;
            foreach ($maal as $value => $key)
              {
                $antal_maal  = $maal[$value];
                $spillernavn = $value;
                $tabel_maal_indhold .= ("
                  <tr>
                    <td width=\"30\" valign=\"top\" align=\"center\">$i_liste.</td>
                    <td width=\"200\" valign=\"top\">$spillernavn</td>
                    <td width=\"70\" valign=\"top\" align=\"center\">$antal_maal</td>
                  </tr>
                ");

                $i_liste ++;
              }

            luk_sqlforbindelse();

            $tabel_samlet = ("
              <table width=\"300\" border=\"$border\" cellpadding=\"2\" cellspacing=\"0\" class=\"Broedtekst\">
                <tr>
                  <td width=\"30\" valign=\"top\" align=\"center\"><b>Nr.</b></td>
                  <td width=\"200\" valign=\"top\"><b>Navn</b></td>
                  <td width=\"70\" valign=\"top\" align=\"center\"><b>Antal mål</b></td>
                </tr>
                $tabel_maal_indhold
              </table>
            ");
          }

        return $tabel_samlet;
      }
  }

Det hele fungerer som det skal, dog kan jeg ikke gennemskue hvordan jeg får ændret lidt i sorteringen.

Som det fungerer nu, bliver listen sorteret efter hvem der har scoret flest mål. Det er også først prioritet, men jeg kunne godt tænke mig at kunne sortere efter navn i anden omgang, altså således at hvis der er tre spillere der alle har scoret samme antal mål, så bliver de listet i alfabetisk rækkefølge.

Hvordan gør jeg?
Avatar billede dennismp Nybegynder
04. september 2004 - 13:33 #1
et forslag:

Gem det sådan her istedet:
$maal[] = array($maal[$navn] + $antal,$navn);

usort($maal,'cmp');

// visning skal så rettes til..
foreach($maal as $entry) {
  $antal_maal = $entry[0];
  $spillernavn = $entry[1];
}

function cmp($a, $b)
{
  if( $a[0] == $b[0] ) {
    if( $a[1] == $b[1] ) return 0;
    return ($a[1] < $b[1]) ? -1 : 1;
  }
  return ($a[0] < $b[0]) ? -1 : 1;
}
Avatar billede Slettet bruger
04. september 2004 - 13:43 #2
Nu er jeg total lost *g*
Kan du venligst forklare hvordan/hvorfor det fungerer?
Avatar billede Slettet bruger
04. september 2004 - 13:48 #3
Fatter ikke en hat.

Jeg har prøvet at flette det ind i koden, højest sandsynlig forkert, da jeg ikke helt forstår hvad der sker.

Sådan ser koden ud nu:
function maal($data)
  {
    if ($data == "maal")
      {
        aabn_sql_og_vaelg_db();

        $sql = ("SELECT * FROM b91_maal, b91_medlemmer
                WHERE b91_maal.spillernr = b91_medlemmer.spillernr");

        $query_maal = mysql_query($sql) or die (mysql_error());

        if (mysql_num_rows($query_maal) < 1 )
          {
            $border = 0;
            // Ingen maalscorer registreret //
          }
        else
          {
            $border = 1;

            while ($row_maal = mysql_fetch_assoc($query_maal))
              {
                $antal      = $row_maal[antal];
                $navn        = $row_maal[navn];

                $maal[] = array($maal[$navn] + $antal,$navn);
              }

            usort($maal,'cmp');

            function cmp($a, $b)
              {
                if( $a[0] == $b[0] )
                  {
                    if( $a[1] == $b[1] ) return 0;
                    return ($a[1] < $b[1]) ? -1 : 1;
                  }
                return ($a[0] < $b[0]) ? -1 : 1;
              }


            $i_liste = 1;
            foreach($maal as $entry)
              {
                $antal_maal = $entry[0];
                $spillernavn = $entry[1];
                $tabel_maal_indhold .= ("
                  <tr>
                    <td width=\"30\" valign=\"top\" align=\"center\">$i_liste.</td>
                    <td width=\"200\" valign=\"top\">$spillernavn</td>
                    <td width=\"70\" valign=\"top\" align=\"center\">$antal_maal</td>
                  </tr>
                ");

                $i_liste ++;
              }

            luk_sqlforbindelse();

            $tabel_samlet = ("
              <table width=\"300\" border=\"$border\" cellpadding=\"2\" cellspacing=\"0\" class=\"Broedtekst\">
                <tr>
                  <td width=\"30\" valign=\"top\" align=\"center\"><b>Nr.</b></td>
                  <td width=\"200\" valign=\"top\"><b>Navn</b></td>
                  <td width=\"70\" valign=\"top\" align=\"center\"><b>Antal mål</b></td>
                </tr>
                $tabel_maal_indhold
              </table>
            ");
          }

        return $tabel_samlet;
      }
  }
Avatar billede Slettet bruger
04. september 2004 - 13:54 #4
Selve visningen af topscorelisten (den originale), kan ses her:
http://www.b91randers.dk/sider/statistik.php?show=maal

Vil gerne have at Andreas er på førstepladsen, Karsten på andenpladsen og Tobias på trediepladsen.

Den tilrettede version kan ses her:
http://www.b91randers.dk/sider/test.php
Avatar billede dennismp Nybegynder
04. september 2004 - 14:07 #5
det virkede vist helt af h.. til :)

Give mig et par minutter, så får du et eksempel der forhåbenlig virker :)
Avatar billede dennismp Nybegynder
04. september 2004 - 14:18 #6
Her er et eksempel (der ser ud til at virke):

http://dennis.moellegaard.dk/v4/php/536206.php?source=2

usort() er en funktion der sorterer efter "brugerens ønske". det andet argument er hvilken funktion der bestemmer om et given element er lig med (returnerer 0), større (1) eller mindre (-1) end et andet element.

I din cmp funktion, skal vi jo så sammenligne mål først - dvs $a[1] vs $b[1] ($a er det ene element fra listen, $b er det andet. Nu skal vi bestemme hvilken elementer der skal først).

Hvis du ser i funktionen, så siger vi (pseudo-agtig):
if( antal mål er ens i de to elementer ) {
  if( hvis navnet er ens ) så returner 0 (elementerne er ens)
  ellers returner hvilket elemnet er størt.
}
ellers returner det element som har flest mål.
Avatar billede Slettet bruger
04. september 2004 - 14:43 #7
Hmmm... kan ikke lige gennemskue hvordan det skal flettes ind i koden.

Sorteringen ser ud til at virke, men jeg skal jo have summeret data'ene først.

Det kan jeg heller ikke få flettet ind i dit eksempel.

Jeg har en tabel, hvori der registreres målscorer for hver kamp.

Dvs. at jeg godt kan have eks. 7 registreringer for en enkelt spiller, hvis vedkommende har scoret i 7 kampe.

Jeg har brug for at hente alle poster i min mål-tabel, og summere antal mål for hver spiller, så jeg ender ud med en liste der indeholder alle de mål hver enkelt spiller har scoret.

Dvs. at disse rækker:

karsten 1
andreas 1
karsten 2
tobias 1
andreas 1
tobias 3
karsten 1
andreas 2
tobias 1

gerne skal summeres ned til:

karsten 4
andreas 4
tobias 5

og så herefter sorteres efter mål, og herefter efter navn:

tobias 5
andreas 4
karsten 4
Avatar billede dennismp Nybegynder
04. september 2004 - 15:08 #8
Du kan faktisk lade MySQL gøre hele arbejdet for dig.

Prøv at rette din SQL til:

$sql = "SELECT navn, sum(antal) as antal FROM b91_maal, b91_medlemmer WHERE b91_maal.spillernr = b91_medlemmer.spillernr GROUP BY navn ORDER BY 2,1";

Så får du faktisk de informationer ud som du ønsker (ved ikke hvorfor jeg ikke tænkte på det før.. :) ) .. Så du bare kan vise dem direkte, uden at skulle bruge arsort,usort eller lign
Avatar billede dennismp Nybegynder
04. september 2004 - 15:09 #9
hov, der var en lille fejl :)

$sql = "SELECT navn, sum(antal) as antal FROM b91_maal, b91_medlemmer WHERE b91_maal.spillernr = b91_medlemmer.spillernr GROUP BY navn ORDER BY 2 DESC,1";
Avatar billede Slettet bruger
04. september 2004 - 17:07 #10
Kanon, det virker.

Læg et svar og der er point på vej :o)
Avatar billede dennismp Nybegynder
04. september 2004 - 17:31 #11
Ok :)
Avatar billede Slettet bruger
04. september 2004 - 19:22 #12
Et lille spørgsmål:
Hvis jeg så har en tabel hvor det f.eks. er antal kampe spillet.

Her har jeg registreret spillernr og kampnr. Disse kan ikke summeres, men SQL har garanteret en eller anden funktion ala sum(), hvor den bare tæller antallet af rækker?

Ved godt jeg kan bruge count() men så skal jeg jo lave en forespørgsel mere der henter de oplysninger jeg skal bruge.

Min sql-forespørgsel ser således ud:

        $sql = ("SELECT * FROM b91_kampe, b91_medlemmer
                WHERE b91_kampe.spillernr = b91_medlemmer.spillernr");

En idé til hvordan den kan kringles?
(der følger selvfølgelig flere point med).
Avatar billede dennismp Nybegynder
04. september 2004 - 20:10 #13
Du behøver ikke at give flere points (ellers skal du oprette et nyt spørgsmål).

Du behøver forresten ikke de paranteser når du tildeler noget til en streng.

Men prøv denne SQL - er ikke helt sikker på at den virker:

$sql = "SELECT b91_medlemmer.*, count(1) FROM b91_kampe, b91_medlemmer
  WHERE b91_kampe.spillernr = b91_medlemmer.spillernr GROUP BY b91_medlemmer";
Avatar billede Slettet bruger
05. september 2004 - 10:29 #14
Den fungerer ikke.

Jeg bruger en mysql_num_rows til at checke om der er nogle poster. Den melder tilbage at der ikke er nogen.
Avatar billede dennismp Nybegynder
05. september 2004 - 11:35 #15
Hvordan ser tabellerne ud? (bare de relevante felter)
Gider du at lave lidt testdata? Bare et par rækker..
Avatar billede Slettet bruger
05. september 2004 - 13:27 #16
Tabellerne ser således ud:

b91_kampe
kampnr - int(6)
spillernr - smallint(3)

b91_medlemmer
navn - varchar(50)
spillernr - smallint(3)

Testdata, i et array?
Avatar billede dennismp Nybegynder
05. september 2004 - 13:52 #17
Ah, fandt på noget selv. Hvis jeg forstod dig rigtig, så vil du tælle hvor mange kampe de forskellige medlemmer har?

SELECT b91_medlemmer.navn, count( 1 )
FROM b91_kampe, b91_medlemmer
WHERE b91_kampe.spillernr = b91_medlemmer.spillernr
GROUP BY b91_medlemmer.navn
Avatar billede Slettet bruger
05. september 2004 - 13:58 #18
Du kan se resultatet af forespørgslen her:
http://www.b91randers.dk/sider/test.php

Hvordan trækker jeg sammentællingen ud?

(uddrag af kode)
while ($row_kampe = mysql_fetch_assoc($query_kampe))
  {
    $antal      = $row_kampe[?????];
    $spillernavn = $row_kampe[navn];
  }
Avatar billede dennismp Nybegynder
05. september 2004 - 14:03 #19
Du retter lidt i sql'en:
SELECT b91_medlemmer.navn, count( 1 ) as antal

"as antal" er tilføjet - nu har du et navn du kan bruge i din $row_kampe (nemlig  $row_kampe['antal'];).
Avatar billede Slettet bruger
05. september 2004 - 14:07 #20
Jeg får ikke noget resultat på.

Min kode er her:
    aabn_sql_og_vaelg_db();

    $sql = ("SELECT b91_medlemmer.navn, count(1) as antal
            FROM b91_kampe, b91_medlemmer
            WHERE b91_kampe.spillernr = b91_medlemmer.spillernr
            GROUP BY b91_medlemmer.navn
            ORDER BY 2 DESC,1 ASC");

    $query_kampe = mysql_query($sql) or die (mysql_error());

    if (mysql_num_rows($query_kampe) < 1 )
      {
        $border = 0;
        $indhold = ("Ingen registreringer.");
      }
    else
      {
        $border = 1;
        $i_liste = 1;

        while ($row_kampe = mysql_fetch_assoc($query_kampe))
          {
            $antal      = $row_kampe[antal];
            $spillernavn = $row_kampe[navn];

            $tabel_kampe_indhold .= ("
              <tr>
                <td width=\"30\" valign=\"top\" align=\"center\">$i_liste.</td>
                <td width=\"200\" valign=\"top\">$spillernavn</td>
                <td width=\"100\" valign=\"top\" align=\"center\">$antal</td>
              </tr>
            ");

            $i_liste ++;
          }

        luk_sqlforbindelse();

        $indhold = ("
          <table width=\"330\" border=\"$border\" cellpadding=\"2\" cellspacing=\"0\" class=\"Broedtekst\">
            <tr>
              <td width=\"30\" valign=\"top\" align=\"center\"><b>Nr.</b></td>
              <td width=\"200\" valign=\"top\"><b>Navn</b></td>
              <td width=\"100\" valign=\"top\" align=\"center\"><b>Antal kampe</b></td>
            </tr>
            $tabel_kampe_indhold
          </table>
        ");
      }
Avatar billede Slettet bruger
05. september 2004 - 14:09 #21
Ehm, skal måske lige huske at uploade min test-side i stedet for den originale.

Det fungerer.

Jeg bliver mere og mere overrasket over hvor godt sql er for hver gang jeg bliver trukket dybere i "sølet" ;o)
Avatar billede Slettet bruger
05. september 2004 - 14:15 #22
Mange tak for hjælpen :o)
Avatar billede dennismp Nybegynder
05. september 2004 - 14:21 #23
Det var så lidt :) ..

Ja, SQL er smart - man gider ikke at bøvle med filer, når man har SQL :)
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
Vi tilbyder markedets bedste kurser inden for webudvikling

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