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.
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...
Eikös ne voisi järjestellä jo kyselyllä?
ORDER BY field1 DESC, field2 ASC, field3 ASC
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?
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.
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ää.
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?
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.