Newsgroup: it.comp.www.php
Titolo: Disposizione dati ricavati da query

Ho due tabella con 2 colonne: Nome e Giorno.
"Nome" è qualcuno che ha compiuto un'azione in determinati giorni
(segnati sulla colonna Giorno). Esempio:
| Marco | 1/1/04 |
| Marco | 2/1/04 |
| Marco | 3/1/04 |
| Piero | 1/1/04 |
| Piero | 3/1/04 |
Nessun problema a scrivere una query che faccia una select e me li
mostri esattamente così come nell'esempio.
Però vorrei visualizzarli in un altro modo, più o meno così (scrivo
con un font a spaziatura fissa):
        1/1/04  2/1/04  3/1/04
Marco   X       X       X
Piero   X       -       X
Avevo pensato di creare una seconda tabella per gestire tutte le
giornate in cui qualcuno ha fatto qualcosa così da avere appunto tutti
i giorni utili alla creazione di quella specie di grafico...
Come si fa a disporre i dati come nell'esempio "delle X"?
-- 
La rovina del mondo sarà l'indifferenza...
...ma chi se fregaaaa!!  :D

 Come si fa a disporre i dati come nell'esempio "delle X"?
con la classica impostazione delle tabelle...
<tr>
    <td>Marco</td><td>X</td><td>-</td><td>X</td>
</tr>
e cosě via...
-- 
===============
Saluti
Web Inside
===============

 Piero   X       -       X
Concettualmente farei: registro in un array le date (giorni[]), in un altro 
i nomi (nomi[]) che compaiono nella tabella. Poi, con 2 cicli for (o con 
while, come preferisci) fai una cosa del tipo (oggi ho voglia di php):
$q="SELECT distinct nome from tabella";
$r=mysql_query($q,$db);
$quantinomicisono=mysql_num_rows($r);
while($ris=mysql_fetch_assoc($r)){
$nomi[]=$ris;
}
$q="SELECT distinct data from tabella";
$r=mysql_query($q,$db);
$quantigiornicisono=mysql_num_rows($r);
while($ris=mysql_fetch_assoc($r)){
$giorni[]=$ris;
}
for($i=0; $i<$quantinomicisono; $i++){
echo "<tr><td>".$nome[$i]."</td>";
for($j=0; $j<$quantigionicisono; $j++){
$q="SELECT * from tabella where nome='".$nome[$i]."' and 
data='".$giorni[$j]."'";
$r=mysql_query($q,$db);
if(mysql_num_rows($r)>0)
echo "<td>x</td>";
else
echo "<td><br></td>";
if($j==$quantigiorni)
echo "</tr>";
}
}
Non testato e da adattare al tuo codice.
CIAO 

 Piero   X       -       X
Metti i risultati in un array, e poi usa una tabella per impaginare i 
risultati 

 CIAO
sotto c'e' il tuo codice indentato e corretto..
ma comunque non credo sia il miglior modo di procedere..
con il tuo codice effettui un numero di query incredibilmente alto che
cresce al crescere del numero di date e di nomi..
con il tuo codice effettui 2+n*m query con n = date ed m = nomi..
quindi in un database con 100 nomi diversi e 50 date diverse effettuerai la
bellezza di 5002 query.. con uno di 500 nomi e 250 date, 125002 query..
posto a boycottbabies un codice che invece effettua 2+n query e che quindi a
parita' di condizioni effettuera' 102 e 502 query (non che il tempo per la
singola query sia lo stesso ma il guadagno in velocita' e memoria e'
comunque evidentemente notevole)..
<?php
echo '<table border=1>';
$result = mysql_query('SELECT distinct nome from tab', $db);
$num_nomi = mysql_num_rows($result);
while($nome = mysql_fetch_assoc($result)){
 $nomi[] = $nome['nome'];
}
$result = mysql_query('SELECT distinct data from tab', $db);
$num_giorni = mysql_num_rows($result);
while($data = mysql_fetch_assoc($result)){
 $giorni[] = $data['data'];
}
for($i = 0; $i < $num_nomi; $i++){
 echo "<tr><td>{$nomi[$i]}</td>";
 for($j = 0; $j < $num_giorni; $j++){
 $result = mysql_query("SELECT * from tab where nome='{$nomi[$i]}' and
data='{$giorni[$j]}'", $db);
 if(mysql_num_rows($result) > 0)
  echo '<td>x</td>';
 else
  echo '<td>-</td>';
 
 if($j == $giorni)
  echo '</tr>';
 }
}
echo '</table>';
?>
-- 
www.iuz-lab.info

mister wrote:

questo e' il codice 2+n (citato a L'Ignorante)..
veloce e compatto (anche migliorabile)..
<?php
$date_list = mysql_query('SELECT data FROM tab WHERE 1 GROUP BY data ORDER
BY data ASC');
echo "<table border='1'><tr><td>Tabella</td>";
while($date = mysql_fetch_assoc($date_list)){
 echo "<td>{$date['data']}</td>";
 $date_array[] = $date['data'];
}
echo '</tr>';
$name_list = mysql_query("SELECT DISTINCT nome FROM tab WHERE 1");
while($name = mysql_fetch_assoc($name_list)){
 echo "<tr><td>{$name['nome']}</td>";
 $x_list = mysql_query("SELECT data FROM tab WHERE nome = '{$name['nome']}'
GROUP BY data ORDER BY data ASC");
 $status = mysql_fetch_assoc($x_list);
 
 reset($date_array);
 while(list(, $data) = each($date_array)){
  echo '<td>';
  if($status['data'] == $data){
   echo 'x';
   $status = mysql_fetch_assoc($x_list);
  }
  else 
   echo '-';   
  echo '</td>';


 CIAO
sotto c'e' il tuo codice indentato e corretto..
ma comunque non credo sia il miglior modo di procedere..
con il tuo codice effettui un numero di query incredibilmente alto che
cresce al crescere del numero di date e di nomi..
con il tuo codice effettui 2+n*m query con n = date ed m = nomi..
quindi in un database con 100 nomi diversi e 50 date diverse effettuerai la
bellezza di 5002 query.. con uno di 500 nomi e 250 date, 125002 query..
posto a mister un codice che invece effettua 2+n query e che quindi a
parita' di condizioni effettuera' 102 e 502 query (non che il tempo per la
singola query sia lo stesso ma il guadagno in velocita' e memoria e'
comunque evidentemente notevole)..
<?php
echo '<table border=1>';
$result = mysql_query('SELECT distinct nome from tab', $db);
$num_nomi = mysql_num_rows($result);
while($nome = mysql_fetch_assoc($result)){
 $nomi[] = $nome['nome'];
}
$result = mysql_query('SELECT distinct data from tab', $db);
$num_giorni = mysql_num_rows($result);
while($data = mysql_fetch_assoc($result)){
 $giorni[] = $data['data'];
}
for($i = 0; $i < $num_nomi; $i++){
 echo "<tr><td>{$nomi[$i]}</td>";
 for($j = 0; $j < $num_giorni; $j++){
 $result = mysql_query("SELECT * from tab where nome='{$nomi[$i]}' and
data='{$giorni[$j]}'", $db);
 if(mysql_num_rows($result) > 0)
  echo '<td>x</td>';
 else
  echo '<td>-</td>';
 
 if($j == $giorni)


?>
Grazie per il codice... effettivamente quello che chiedevo era (per
me) molto complesso. Ancora sto cercando di capire cosa ho
trascritto...
Comunque c'è un piccolo problema: la tabella che si va a formare è
"sfasata" di un td. In pratica viene visualizzata così:
                 1/1/04  2/1/04  3/1/04
 Marco   X       X       X
 Piero   X       -       X
Cosa può essere?


Cosa può essere?
Per ora ho risolto aggiungendo un <td></td> in più nel ciclo che
scrive i nomi... Sembra funzionare...


 
mi sembra strano, a me funziona bene.. 
hai modificato il codice di questa riga?
echo "<table border='1'><tr><td>Tabella</td>";
o di qualche altra?
potresti postare l'html generato dal codice colpevole?
-- 
www.iuz-lab.info

> giornate in cui qualcuno ha fatto qualcosa cosě da avere appunto tutti

Mi sorge una domanda: ma a questo punto non si potrebbe fare UNA SOLA query? 
Cioč, metto i record in un array bidimensionale e faccio i controlli su di 
esso. Dici che poi dal punto di vista computazionale e dell'implementazione 
diventerebbe troppo oneroso o č a priori non fattibile? 

Secondo me un MINIMO di due query devi per forza farlo (a meno di non 
rendere ancora piů compliicata la query che ti incollerň piů avanti).
Con la prima query vedi quali sono le date presenti nel tuo archivio, e 
crei l'intestazione della tabella HTML.
Con la seconda query ottieni una terza colonna che ti dice per ogni 
persona e per ogni data se quella persona in quella data ha eseguito 
un'operazione.
Mi spiego.
Fingiamo che la tua tabella mysql si chiami OPERAZIONI e che sia cosě 
popolata:
+-----------+------------+
| persona   | data       |
+-----------+------------+
| Antonello | 2004-01-12 |
| Antonello | 2004-02-25 |
| Claudio   | 2004-01-15 |
| Claudio   | 2004-09-05 |
| Claudio   | 2004-10-15 |
| Luigi     | 2004-01-15 |
| Luigi     | 2004-05-09 |
| Luigi     | 2004-06-14 |
| Marco     | 2004-01-12 |
| Marco     | 2004-09-08 |
+-----------+------------+
io farei una prima query del tipo:
SELECT DISTINCT data FROM operazioni ORDER BY data ASC;
e scorrendo con php il recordset ottenuto creerei l'intestazione della 
tabella html.
A questo punto eseguirei la seconda query:
SELECT	tmp.persona,
	tmp.data,
	IF(op.persona IS NULL, '', 'X') AS x
FROM
  (
    SELECT DISTINCT o1.persona, o2.data
    FROM operazioni o1, operazioni o2
    ORDER BY persona ASC, data ASC
  ) AS tmp
LEFT JOIN operazioni op
ON  tmp.persona=operazioni.persona
AND tmp.data=operazioni.data
che dalla tabella di cui sopra ottieni:
+-----------+------------+---+
| persona   | data       | X |
+-----------+------------+---+
| Antonello | 2004-01-12 | X |
| Antonello | 2004-01-15 |   |
| Antonello | 2004-02-25 | X |
| Antonello | 2004-05-09 |   |
| Antonello | 2004-06-14 |   |
| Antonello | 2004-09-05 |   |
| Antonello | 2004-09-08 |   |
| Antonello | 2004-10-15 |   |
| Claudio   | 2004-01-12 |   |
| Claudio   | 2004-01-15 | X |
| Claudio   | 2004-02-25 |   |
| Claudio   | 2004-05-09 |   |
| Claudio   | 2004-06-14 |   |
| Claudio   | 2004-09-05 | X |
| Claudio   | 2004-09-08 |   |
| Claudio   | 2004-10-15 | X |
| Luigi     | 2004-01-12 |   |
| Luigi     | 2004-01-15 | X |
| Luigi     | 2004-02-25 |   |
| Luigi     | 2004-05-09 | X |
| Luigi     | 2004-06-14 | X |
| Luigi     | 2004-09-05 |   |
| Luigi     | 2004-09-08 |   |
| Luigi     | 2004-10-15 |   |
| Marco     | 2004-01-12 | X |
| Marco     | 2004-01-15 |   |
| Marco     | 2004-02-25 |   |
| Marco     | 2004-05-09 |   |
| Marco     | 2004-06-14 |   |
| Marco     | 2004-09-05 |   |
| Marco     | 2004-09-08 | X |
| Marco     | 2004-10-15 |   |
+-----------+------------+---+
Praticamente un prodotto cartesiano in cui ogni persona č confrontata 
con tutte le date possibili presenti. Se la persona in quella data ha 
eseguito un'operazione, la colonna X contiene appunto 'X'.
Ora non ti resta che scorrere questo recordset e creare un <tr> per ogni 
persona e tanti <td> quante sono le date.
Dato che si tratta di un prodotto cartesiano puoi stare tranquillo che 
per ogni persona ci sono esattamente tante date quante ne hai ottenute 
con la prima query quindi fai con un for o un while :)
-- 
Quando noi ignoranti eravamo di piů, tutto era piů bello...
(A. Celentano)
Per rispondermi in privato, togli prima l'immondizia dalla testa ;)

 fattibile?
e' fattibile ma dovresti selezionare tutta la tebella ed ordinarne il
contenuto all'interno di un'array..
puo' essere conveniente con tabelle molto piccole..
e comunque se crei solo un array 2d saresti costretto ad aumentarne le
dimensioni fino ad avere tutte le combinazioni nome data possibili..
credo che scorrere la tabella sia la strategia migliore..
l'unica cosa da determinare e' se scorrerla per nomi o date, ed io ho scelto
i nomi poiche' ho assunto che ci siano meno nomi che date (ed anche perche'
le tabelle in html si scrivono per righe)(nomi sulle colonne e date al lato
potrebbe anche essere una miglioria, se le date distinte sono in numero
minore dei nomi).. 
comunque fai qualche prova, magari trovi un sistema migliore, o contraddici
la mia supposizione (la tabella oltretutto potrebbe essere anche
normalizzata)..
-- 
www.iuz-lab.info

 
con una tabella piu' grande ti ritroveresti a scorrere un recordset troppo
lungo..
-- 
www.iuz-lab.info

Beh ricordo che da qk parte nel thread si sia chiesto se fosse stato 
possibile recuperare tutto tramite query.
La soluzione sarebbe questa.
Ammesso di usare una tabella con la struttura identica alla mia 2 post 
fa, il codice grosso modo sarebbe questo:
<table border="1" cellspacing="1" cellpadding="1" width="700">
<tr>
   <td>Persona</td>
<script language="php">
   $conn=mysql_connect("localhost", "root", "");
   mysql_select_db("test");
   $rs=mysql_query("SELECT DISTINCT data FROM operazioni ORDER BY data 
ASC");
   while ($riga=mysql_fetch_array($rs))
   {
      printf("<td>$riga[data]</td>");
   };
</script>
<script language="php">
   $strquery="SELECT	tmp.persona,".
	    "tmp.data, ".
	    "IF(op.persona IS NULL, '&nbsp;', 'X') AS x ".
             "FROM ".
             " ( ".
             "   SELECT DISTINCT o1.persona, o2.data ".
             "   FROM operazioni o1, operazioni o2 ".
             "   ORDER BY persona ASC, data ASC ".
             " ) AS tmp ".
             "LEFT JOIN operazioni op ".
             "ON  tmp.persona=op.persona ".
             "AND tmp.data=op.data";
    $persona="";
    $rs=mysql_query($strquery) or die("Errore nella query");
    while ($riga=mysql_fetch_array($rs))
    {
      if ($persona!=$riga[persona])
      {
        if ($persona=="") printf("\n</tr>\n");
        $persona=$riga[persona];
        printf("<tr><td>$riga[persona]</td>\n");
      };
      printf("<td align='center'>$riga[x]</td>\n");
    };
    mysql_close($conn);
</script>
</tr>
</table>
Ovviamente se si devono visualizzare solo un certo mese allora le query 
vanno ritoccate un pochino, ma in generale funziona.
Ovviamente, col crescere delle persone da visualizzare ovviamente cresce 
di parecchio il recordset che si ottiene...
-- 
Quando noi ignoranti eravamo di più, tutto era più bello...


 di parecchio il recordset che si ottiene...
Ovviamente :)
Scusate è quasi l'una... ho programmato tutto il giorno e siccome sto 
imparando php ora dopo ora (questioni lavorative), mi è sembrato un 
esercizio utile, ma la notte è alta e sono sveglio :)
Non so nemmeno cosa sto scrivendo... l'italiano va a farsi friggere 
mentre le righe di codice venngono buttate giù correttamente. C'è un 
problema ;)


potresti postare l'html generato dal codice colpevole?
Chiedo umilmente scusa... ho fatto una stron###a.
Il codice che avevi postato non l'ho "incollato" ma riscritto. Volevo
capire quello che facevo quindi col copia/incolla avrei avuto solo
confusione.
Ho fatto un errore di "frettolosità" scrivendo:
<td>Tabella<td>
anzichè
<td>Tabella</td>
 
 :-(((((
