Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: mysql-kyselyn ryhmitteleminen useamman sarakkeen mukaan

Sivun loppuun

Cartter [01.07.2009 13:49:15]

#

PDOStatement
array fetchAll ([ int $fetch_style [, int $column_index [, array $ctor_args ]]])

fetch_style
To return an associative array grouped by the values of a specified column, bitwise-OR PDO::FETCH_COLUMN with PDO::FETCH_GROUP

---
/* Fetch all of the values of the first column */
var_dump($sth->fetchAll(PDO::FETCH_COLUMN, 0));

/* Group values by the first column */
var_dump($sth->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP));
---

Kysymykseni kuuluu, että kuinka saan ryhmiteltyä kyselyn tulokset useamman sarakkeen mukaan? Vai saako tämän toteutettua mysql-kyselyllä paremmin?..Jos saa niin mielellään lukisin esimerkin.

Metabolix [01.07.2009 14:11:49]

#

Ainakin voit tehdä ryhmittelyn helposti PHP:n puolella.

<?php
function group_by($data, $group_columns) {
  $ret = array();
  foreach ($data as $r) {
    $arr = &$ret;
    foreach ($group_columns as $g) {
      $arr = &$arr[$r[$g]];
      # unset($r[$g]); // Jos optimoidaan tilankäyttöä
      if (empty($arr)) {
        $arr = array();
      }
    }
    $arr[] = $r;
    unset($arr);
  }
  return $ret;
}
$data = group_by($statement->fetchAll(PDO::FETCH_ASSOC), array("hedelma", "lajike"));
var_dump($data);

Edit. Olisiko nyt...

tsuriga [01.07.2009 14:51:37]

#

Eikös ne voisi järjestellä jo kyselyllä?

ORDER BY field1 DESC, field2 ASC, field3 ASC

Cartter [01.07.2009 21:19:54]

#

Juu ORDER:lla saan tuon kyselyn tulokset järjestykseen, mutta haun palauttaman taulukon läpi käyminen halutulla tavalla aiheuttaa hieman ongelmia tällä tavalla. FETCH_GROUP palauttaa tulokset järjestettyinä tietyn sarakkeen mukaan taulukko-muuttujana, mikä on juuri se mitä toivon, koska saan näin paljon helpommin käytyä tuloksia läpi, mutta tuolla ei vissiin saa järjestettyä tuloksia kun yhden sarakkeen mukaan?

tsuriga [02.07.2009 12:04:36]

#

PDO::FETCH_COLUMN|PDO::FETCH_GROUP näyttäisi palauttavan ryhmitellyn taulukon, jossa ensimmäisen kolumnin arvot ja avaimet ovat pyöräytetty nurinperin. Minkälaista taulukkoa käytännössä siis haet? Näin saat kenttien nimet indekseiksi, ja luotua taulukkoa on jo suht helppo käsitellä:

<?php

$query = 'SELECT name, age, email FROM user ORDER BY name, age';

$i = 0;
$arr = array();
foreach ($pdo->query($query, PDO::FETCH_ASSOC) as $row) {
    foreach ($row as $key => $value) {
        if (!isset($arr[$key])) {
            $arr[$key] = array();
        }

        // Discard empty values
        if ($value !== '' && $value !== null) {
            $arr[$key][$i] = $value;
        }
    }

    $i++;
}

print_r($arr);

/*
Array
(
    [name] => Array
        (
            [0] => Matti
            [1] => Pekka
            [2] => Pekka
        )

    [age] => Array
        (
            [0] => 25
            [1] => 20
            [2] => 30
        )

    [email] => Array
        (
            [0] => matti@fi
            [2] => pekka@co.uk
        )

)
*/
?>

Metabolixinkin koodia yritin kokeilla, mutten oikein tiedä, miten sen on tarkoitus toimia. FetchAll on PDOStatement-luokan kutsu (joten muuttujan nimenä olisi loogisempaa käyttää esim. $stmt), eikä muuttujaa $pdo määritellä funktiossa. Jos funktiossa vaihtaa $pdo->fetchAll tilalle $data, tuloksena on kasa indeksivirheitä sekä hankalan näköinen taulukko.

Metabolix [02.07.2009 14:02:27]

#

tsuriga kirjoitti:

Metabolixinkin koodia yritin kokeilla, mutten oikein tiedä, miten sen on tarkoitus toimia. FetchAll on PDOStatement-luokan kutsu (joten muuttujan nimenä olisi loogisempaa käyttää esim. $stmt), eikä muuttujaa $pdo määritellä funktiossa. Jos funktiossa vaihtaa $pdo->fetchAll tilalle $data, tuloksena on kasa indeksivirheitä sekä hankalan näköinen taulukko.

Tuo oli aivan oikea muutos, ja luulisi kaikille olevan aivan selvää, että tuossa oli virhe, kun kerran fetchAllin paluuarvo annetaan jo funktiolle argumenttina. (Korjasin aiemman viestin.) Tuon muutoksen jälkeen koodi toimii eikä tuota oikein käytettynä yhtäkään indeksivirhettä. Jälkimmäinen parametri on lista ryhmittelyyn käytettävistä sarakkeista, ja tuloksena ei ole "hankala taulukko" vaan luultavasti juuri se, mitä kysyjä kaipasi.

<?php
foreach ($data as $hedelma => $lajikkeet) {
  foreach ($lajikkeet as $lajike => $tiedot) {
    echo "Hedelmän {$hedelma} lajike {$lajike} on väriltään {$tiedot['vari']}.\n";
  }
}

Edit. Alkuperäisen hakufunktion mukaan itse asiassa näin:

<?php
foreach ($data as $hedelma => $lajikkeet) {
  foreach ($lajikkeet as $lajike => $varit) {
    foreach ($varit as $t) {
      echo "Hedelmän {$hedelma} lajike {$lajike} voi olla {$t['vari']}.\n";
    }
  }
}

Pahoittelen heikkoa dokumentaatiota, mutta funktio on itselleni niin triviaali, että oletin, että se olisi helppo ymmärtää.

tsuriga [02.07.2009 18:19:34]

#

Mea culpa, indeksivirheet (ja täten hankalan näköinen taulukko) tulivat siitä ko testasin silmät ummessa väärillä parametreilla. Eikö haluttuun lopputulokseen pääse mitenkään helpommalla?

<?php

$query = 'SELECT hedelma, lajike, vari FROM kori GROUP BY hedelma DESC, lajike';

foreach ($pdo->query($query, PDO::FETCH_ASSOC) as $row) {
    echo "Hedelmän {$row['hedelma']} lajike {$row['lajike']} ja väri $row['vari']}.\n";
}

Metabolix [03.07.2009 08:38:29]

#

Esimerkkini tarkoitus oli näyttää, millainen taulukko tulee, ja toiminta tuskin vastaa sitä, mihin tuota on tarkoitus käyttää. Tuollahan voi hakea esimerkiksi laulut listattuna esittäjän ja levyn mukaan, ja kun sitten toisessa kyselyssä hakee ne esittäjät ja kolmannessa levyt, on helppo tehdä listauksia, joissa toistuvat tiedot tulostetaan vain kerran:

<?php
// Haetaan taulukot $esittajat, $levyt ja $kappaleet
foreach ($kappaleet as $esittaja => $esittajan_kappaleet) {
  $esittaja = $esittajat[$esittaja];
  echo "{$esittaja['nimi']}:\n";
  foreach ($esittajan_kappaleet as $levy => $levyn_kappaleet) {
    $levy = $levyn[$levy];
    echo "\t{$levy['nimi']}:\n";
    foreach ($levyn_kappaleet as $kappale) {
      echo "\t\t{$kappale['nimi']}\n";
    }
  }
}
Seminaarinmäen mieslaulajat
  Sampo Texas
    Kaksi kättä hississä
    Paska maanantai
  Wunderbaum
    Taina
    Oboe ja maito
Kake Singers
  20 suosikkia
    Kakerock
    Ruisleipä Boogie

Onnistuu tämä tietysti ilmankin taulukkolajittelua, kuten olen itse juuri biisilistauksen tapauksessa demonstroinut.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta