Count dei valori duplicati in un array ordinato

carlo9987

Utente Attivo
5 Mar 2013
35
0
0
Roma
Ciao a tutti!

Sono di nuovo qui a chiedere il vostro aiuto, che finora è stato prezioso!!

Ho un array (ordinato) con una serie di valori duplicati, quello che vorrei fare è eliminare i duplicati e conteggiarli per mese.

Così realizzo l'intestazione della tabella:

PHP:
echo "<table id='tableResult' border='0' width='100%'>";
echo "<tr style='font-family: Tahoma; font-size:2,3px'><td><b>NOME</b></td><td><b>Provincia</b></td><td><b>Categoria</b></td><td><b>AMB</b></td><td><b>SPEC</b></td><td><b>Mese</b></td>";
				
foreach(datediff($_POST['startDate'], $_POST['endDate']) as $mesi){
        echo "<td><b>";
        echo getNameMonth($mesi); # Con questa funzione estraggo i nomi dei mesi selezionati tramite textbox
	echo "</b><td>";
}

...

Qui invece creo l'array con i risultati della query:

PHP:
$queryResult = mssql_query($queryResultStr);
while($rowResult = mssql_fetch_array($queryResult)){
				
	$NomeNew = $rowResult["Nome"];
	$provinciaNew = $rowResult["Provincia"];
	$categoriaNew = $rowResult["Categoria"];
	$ambNew = $rowResult["AMB"];
	$specNew = $rowResult["SPEC"];
	$MeseNew = substr($rowResult["startDate"],8,2);
								
	$arrayResult[] = "<tr style='font-family: Tahoma' class='".str_replace(" ","",$NomeNew)." ".$provinciaNew." ".$categoriaNew." ".str_replace(" ","",str_replace(".","",$ambNew))." ".str_replace(".","",$specNew)."'><td>".$isfNew."</td><td>".$provinciaNew."</td><td>".$categoriaNew."</td><td>".$ambNew."</td><td>".$specNew."</td></tr>"; #Prima della chiusura del TR andrebbero i conteggi per mese

}

...

Vorrei ottenere un risultato del genere:

Nome | Provincia | Categoria | AMB | SPEC | Febbraio | Marzo
MARCO ROSSI NA CAT A AMB B SPEC C 2 3
MARCO ROSSI NA CAT B AMB B SPEC C 5 6
MARCO ROSSI NA CAT C AMB B SPEC C 2 1

Spero di aver reso l'idea! Vi ringrazio in anticipo!!
 
Ultima modifica:
Ciao, secondo me se modifichi la query ad hoc puoi farti restituire i dati come ti servono
puoi usare funzioni come GROUP BY e COUNT()
 
Purtroppo nel mio caso vorrei evitare di lavorare sulla query, già ora ho dei tempi di risposta abbastanza alti (10/15 secondi)..... :crying:

Ciao, secondo me se modifichi la query ad hoc puoi farti restituire i dati come ti servono
puoi usare funzioni come GROUP BY e COUNT()
 
allora forse è proprio il caso di rivedere la query
cmq per trovare i valori duplicati prova a prendere spunto da questo codice
http://forum.mrwebmaster.it/php/28352-contare-valori-uguali-array-dividerli-stringa.html#post103500

Purtroppo non so quanto sia possibile sistemare la query, fa una semplice select con 3 where e senza alcun join.. All'interno della tabella ci saranno circa 700 mila record. Provo la soluzione da te suggerita, sembra essere perfetta!

Come al solito ti ringrazio per la tempestività e soprattutto disponibilità! :fonzie:

Provo e ti aggiorno..
 
700mila record? Di solito si evita di avere così tanti record in un'unica tab a meno che non sia proprio necessario perché appunto rallenta l'esecuzione delle query.
 
Hai provato a cambiare la query?
Poi confronta i tempi di risposta.
 
Hai provato a cambiare la query?
Poi confronta i tempi di risposta.

Più semplice di così non saprei farla:

select Nome, Provincia, Categoria, AMB, SPEC, startDate from vtlcontattiriep where userIdLogIn = '".$DM."' and startDate between '".$start."' and '".$end."' ORDER BY Nome, Provincia, Categoria, AMB, SPEC
 
forse dovresti dire al tuo collega di mettere qualche indice sulla tabella
la query è semplicissima l'ho provata simile su una mia tabella che ha oltre 1 milione di record
Codice:
SELECT idLog, desc, log, idProdotto, fornitore
FROM `log`
WHERE data
BETWEEN "2012-01-01"
AND "2013-03-27"
Codice:
Mostrando i righi 0 - 29 ( 1,128,389 totale, La query ha impiegato 0.0020 sec)

edit
in effetti se li mostro tutti ci impiega 8 secondi
ma li cerchi sempre tutti?
 
Ultima modifica:
C'è da dire che poi fai n! (Male che ti vada) confront per vedere se è ordinato no?
Non ho visto il codice che fa il controllo per i duplicati.
Sei riuscito a fare qualcosa con il link del thread postato da criric?
 
forse dovresti dire al tuo collega di mettere qualche indice sulla tabella
la query è semplicissima l'ho provata simile su una mia tabella che ha oltre 1 milione di record
Codice:
SELECT idLog, desc, log, idProdotto, fornitore
FROM `log`
WHERE data
BETWEEN "2012-01-01"
AND "2013-03-27"
Codice:
Mostrando i righi 0 - 29 ( 1,128,389 totale, La query ha impiegato 0.0020 sec)

edit
in effetti se li mostro tutti ci impiega 8 secondi
ma li cerchi sempre tutti?

No no, non sempre, ma in alcuni casi si.

Lasciamo stare il collega, è meglio! E' di una disponibilità unica, per non parlare della tantissima voglia di fare! :incazz:

Comunque teoricamente pensavo ad una soluzione del genere:

- Creare un array utilizzando la funzione array_unique;
- Cercare per ogni record le corrispondenze nell'array nativo e contarle, (creando record differenti in base al mese) ed inserirle conteggiate in un nuovo array (come potrei farlo questo?);
- Cercare per ogni record le corrispondenze nell'array nativo, fare una substr estaendo il conteggio per mese e fare un merge su un'unica stringa.

Secondo voi è fattibile??

Grazie mille.
 
È una possibile soluzione.
Io ho pensato a qualcosa che ti fa risparmiare tempo visto che ci vuol già molto per caricare la query.
PHP:
$elem_ripetuti = array_unique(array_diff_assoc($tuo_array,array_unique($tuo_array)));
In questo modo $elem_ripetuti contiene tutti e solo gli elementi ripetuti 2 o più volte quindi ti basta contare questi e tutti gli altri sono ripetuti una sola volta.
Ora che hai questi elementi li confronti con quelli dell'array originario per vedere quante volte sono ripetuti.
 
È una possibile soluzione.
Io ho pensato a qualcosa che ti fa risparmiare tempo visto che ci vuol già molto per caricare la query.
PHP:
$elem_ripetuti = array_unique(array_diff_assoc($tuo_array,array_unique($tuo_array)));
In questo modo $elem_ripetuti contiene tutti e solo gli elementi ripetuti 2 o più volte quindi ti basta contare questi e tutti gli altri sono ripetuti una sola volta.
Ora che hai questi elementi li confronti con quelli dell'array originario per vedere quante volte sono ripetuti.

Allora, partendo dal tuo suggerimento ho cambiato la query (impiega circa 2 secondi in più, quindi mi può star bene):

PHP:
$queryResultStr = "select Nome, Provincia, Categoria, AMB, SPEC, MONTH(startDate) as Mese, COUNT(MONTH(startDate)) as Totale from vtlcontattiriep where userIdLogIn = '".$DM."' and startDate between '" . $starty . "-" . $startm . "-" . $startd ." 00:00:00' and '" . $endy . "-" . $endm . "-" . $endd ." 23:59:59' GROUP BY Nome, Provincia, Categoria, AMB, SPEC, MONTH(startDate) ORDER BY Nome, Provincia, Categoria, AMB, SPEC";

Chiaramente così, il risultato sarà un record per ogni mese, quindi:

Nome Provincia Categoria AMB SPEC Mese Totale
Carlo NA cat_A amb_A spec_B 1 3
Carlo NA cat_A amb_A spec_B 2 6


Mentre quello che vorrei ottenere io è:

Nome Provincia Categoria AMB SPEC Gennaio Febbraio Totale
Carlo NA cat_A amb_A spec_B 3 6 9



Suggerimenti????? :dipser:
 
Be' lo potevi dire prima. Come ti aveva già suggerito criric utilizzando il Group BY e count() puoi ottenere tutto già dalla query senza manipolare con php.
 
Be' lo potevi dire prima. Come ti aveva già suggerito criric utilizzando il Group BY e count() puoi ottenere tutto già dalla query senza manipolare con php.

Si scusatemi!! Il discorso è che di regola non dovrei toccare le query perchè dovrebbe fornirmele un collega in base ai tempi di risposta, però in questo caso ragionandoci è un suicidio, quindi gliene ho parlato e l'abbiamo cambiata...
 
Dovresti utilizzare qualcosa del tipo:
Codice:
SUM(IF(month = "gennaio", 1,0)) AS `gennaio`,
SUM(IF(vote = "febbraio", 1,0)) AS `febbraio`,
...
 

Discussioni simili