Problema query MySQL

  • Creatore Discussione Creatore Discussione mephjl
  • Data di inizio Data di inizio

mephjl

Nuovo Utente
7 Mar 2012
9
0
0
Salve a tutti,

ho un database MySQL con una tabella che ha quasi 200000 righe e 25 colonne, uso EasyPHP per fare le mie prove in locale, un campo è di tipo data 'Y-m-d', la mia quey è la seguente :

$query = "SELECT * FROM TABELLA WHERE giorno >= '$date1' AND giorno <= '$date2'";

il problema è che se l'arco di tempo tra $date1 e $date2 è elevato, non mi restituisce il risultato, e cioè almeno vorrei sapere quante righe sono con un semplice count.
Mi ritrovo con l'errore di aver superato il limite massimo di tempo per la query.

Potete aiutarmi in qualche modo ?

Ringrazio tutti anticipatamente.
 
ciao
per vedere quante righe sono
PHP:
<?php
//.....
$query = "SELECT * FROM TABELLA WHERE giorno >= '$date1' AND giorno <= '$date2'";
$ris=mysql_query($query);
$le_righe_sono=mysql_num_rows($ris);
//....
?>
se poi il tempo di elaborazione è troppo lungo puoi allungare la vita dellp script (standard 30 sec) con
PHP:
set_time_limit ( $secondi ); //$secondi numero intero di secondi es 3600 (01 ora)

però forse la soluzione migliore è fare una paginazione in modo da estrarre un numero limitato di record alla volta
 
Ciao,
prova anche con BEETWEN dovrebbe essere piu veloce

PHP:
$query = "SELECT * FROM TABELLA WHERE giorno BETWEEN '$date1' AND '$date2'";

se ti interessano anche i dati compresi della variabile $date2 devi aggiungere

PHP:
$query = "SELECT * FROM TABELLA WHERE giorno BETWEEN '$date1' AND DATE_ADD('$date2',INTERVAL 1 DAY)";
 
prima di tutto, grazie per le risposte, molto gentili, ma il problema si è complicato.

Avevo risolto quel problema eliminando altre situazioni che esistevano prima, praticamente ho alleggerito tyutto il codice facendo fare a questa pagina solo questo.
Ora ho :

$query = "SELECT e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20 FROM 'TABELLA' WHERE giorno >= '$date1' AND giorno <= '$date2'";
$result = mysql_query($query);
$row = mysql_num_rows($result);// NUMERO DI RIGHE

e fin qui ci siamo, va bene, poi :

while ($row = mysql_fetch_array($result, MYSQL_NUM)) {


$query = "SELECT e1, e2 FROM 'ALTRA TABELLA'";
$result1 = mysql_query($query);

while ($row1 = mysql_fetch_array($result1, MYSQL_NUM)) {
$numero1 = $row1[0];
$numero2 = $row1[1];

if (in_array($numero1,$row ) && in_array($numero2,$row )) {
$coppia[$numero1][$numero2] = $coppia[$numero1][$numero2] + 1;
}

}


Praticamente ho bisogno di sapere quante volte escono quei due numeri in quel range di giorni.

Facendo la prima query tra pochi giorni di distanza TUTTO VA BENE, appena allargo il range PAGINA BIANCA, per eseguire lo script ci vuole troppo tempo (più di 30 sec)

SOLUZIONI ?

Sono in mano a voi.
 
Ultima modifica:
ciao,
a dir la verita ho capito poco il tuo codice

PHP:
<?php

$query = "SELECT e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20,
                 
                 FROM 'TABELLA' WHERE giorno >= '$date1' AND giorno <= '$date2'";
$result = mysql_query($query);
//cambia nome variabile visto che poi usi la stessa per fare altro
$numero_righe = mysql_num_rows($result); // NUMERO DI RIGHE
//
//e fin qui ci siamo, va bene, poi :

// , MYSQL_NUM dovrebbe essere una costante? a che serve?

while ($row = mysql_fetch_array($result, MYSQL_NUM)) {

    // questa probabilmente la puoi togliere

    $query = "SELECT e1, e2 FROM 'ALTRA TABELLA'";
    $result1 = mysql_query($query);
    // mi fermo qui e ti faccio qualche domanda
    // exit();
    while ($row1 = mysql_fetch_array($result1, MYSQL_NUM)) {
        $numero1 = $row1[0];
        $numero2 = $row1[1];

        if (in_array($numero1, $row) && in_array($numero2, $row)) {
            $coppia[$numero1][$numero2] = $coppia[$numero1][$numero2] + 1;
        }
    }
    // manca una }
}
?>

Cosa contengono i campi e1 e e2?
perche li cerchi in un altra tabella?

penso sia sufficente scrivere
while ($row1 = mysql_fetch_array($result)) {

la query che fai nel ciclo while è da evitare

Sicuramente ci si puo arrivare in un altro modo
 
allora spiego meglio cosa devo fare perchè penso che mi sono talmente impappinato ormai che non ne esco + e che si possa arrivare alla soluzione anche in modo diverso.

Io ho 2 tabelle di numeri,
nella prima tabella ho e1 ed e2 che sono una coppia con relativo id chiaramente,
nella seconda ho e1,e1,e3..... che sono 20 numeri ed io devo cercare all'interno di questa tabella quante volte escono e1 ed e2 della prima in un arco temporale.

immagina :

1 3 6 7 9 10 13 24 25 26 30 32 33 34 56 78 79 81 84 89 (20 numeri) con una data
1 2 3 4 5 6 7 8 9 24 45 56 57 58 59 64 68 70 80 90 stessa o diversa data
.......................................
e voglio sapere le coppie che sono uscite e quante volte da una data all'altra.

perchè la seconda tabella praticamente contiene

1 2
1 3
1 4
1 5
etc ............

spero di essere stato chiaro stavolta...e cmq GRAZIEEEEE
 
Se non sbaglio di grosso con questa query dovresti risolvere il problema in un colpo solo:

Codice:
SELECT num1,num2, COUNT(*) AS totale FROM t1, t2
WHERE (
  t1.e1 = t2.num1 OR
  t1.e2 = t2.num1 OR
  t1.e3 = t2.num1 OR
  t1.e4 = t2.num1 OR
  t1.e5 = t2.num1 OR
  t1.e6 = t2.num1 OR
  t1.e7 = t2.num1 OR
  t1.e8 = t2.num1 OR
  t1.e9 = t2.num1 OR
  t1.e10 = t2.num1 OR
  t1.e11 = t2.num1 OR
  t1.e12 = t2.num1 OR
  t1.e13 = t2.num1 OR
  t1.e14 = t2.num1 OR
  t1.e15 = t2.num1 OR
  t1.e16 = t2.num1 OR
  t1.e17 = t2.num1 OR
  t1.e18 = t2.num1 OR
  t1.e19 = t2.num1 OR
  t1.e20 = t2.num1
) AND (
  t1.e1 = t2.num2 OR
  t1.e2 = t2.num2 OR
  t1.e3 = t2.num2 OR
  t1.e4 = t2.num2 OR
  t1.e5 = t2.num2 OR
  t1.e6 = t2.num2 OR
  t1.e7 = t2.num2 OR
  t1.e8 = t2.num2 OR
  t1.e9 = t2.num2 OR
  t1.e10 = t2.num2 OR
  t1.e11 = t2.num2 OR
  t1.e12 = t2.num2 OR
  t1.e13 = t2.num2 OR
  t1.e14 = t2.num2 OR
  t1.e15 = t2.num2 OR
  t1.e16 = t2.num2 OR
  t1.e17 = t2.num2 OR
  t1.e18 = t2.num2 OR
  t1.e19 = t2.num2 OR
  t1.e20 = t2.num2
) AND giorno >= '2000-01-01' AND giorno <= '2011-12-31'
GROUP BY CONCAT(num1,num2)

Prima di usarla meglio che fai qualche prova con un set di dati limitato per verificare i risultati
 
Se non sbaglio di grosso con questa query dovresti risolvere il problema in un colpo solo:

Codice:
SELECT num1,num2, COUNT(*) AS totale FROM t1, t2
WHERE (
  t1.e1 = t2.num1 OR
  t1.e2 = t2.num1 OR
  t1.e3 = t2.num1 OR
  t1.e4 = t2.num1 OR
  t1.e5 = t2.num1 OR
  t1.e6 = t2.num1 OR
  t1.e7 = t2.num1 OR
  t1.e8 = t2.num1 OR
  t1.e9 = t2.num1 OR
  t1.e10 = t2.num1 OR
  t1.e11 = t2.num1 OR
  t1.e12 = t2.num1 OR
  t1.e13 = t2.num1 OR
  t1.e14 = t2.num1 OR
  t1.e15 = t2.num1 OR
  t1.e16 = t2.num1 OR
  t1.e17 = t2.num1 OR
  t1.e18 = t2.num1 OR
  t1.e19 = t2.num1 OR
  t1.e20 = t2.num1
) AND (
  t1.e1 = t2.num2 OR
  t1.e2 = t2.num2 OR
  t1.e3 = t2.num2 OR
  t1.e4 = t2.num2 OR
  t1.e5 = t2.num2 OR
  t1.e6 = t2.num2 OR
  t1.e7 = t2.num2 OR
  t1.e8 = t2.num2 OR
  t1.e9 = t2.num2 OR
  t1.e10 = t2.num2 OR
  t1.e11 = t2.num2 OR
  t1.e12 = t2.num2 OR
  t1.e13 = t2.num2 OR
  t1.e14 = t2.num2 OR
  t1.e15 = t2.num2 OR
  t1.e16 = t2.num2 OR
  t1.e17 = t2.num2 OR
  t1.e18 = t2.num2 OR
  t1.e19 = t2.num2 OR
  t1.e20 = t2.num2
) AND giorno >= '2000-01-01' AND giorno <= '2011-12-31'
GROUP BY CONCAT(num1,num2)

Prima di usarla meglio che fai qualche prova con un set di dati limitato per verificare i risultati



Scusa ma num1 e num2 cambiano non sono sempre gli stessi, magari spiegami bene sta query grazie
 
Allora vediamo:

Codice:
SELECT num1,num2, COUNT(*) AS totale FROM t1, t2

Questa parte effettua una CROSS JOIN delle due tabelle (in pratica il prodotto cartesiano, cioè combina ogni riga di una tabella con ogni riga dell'altra tabella).
Quindi se la tabella t1 ha 200 record e la seconda 50 il risultato saranno 200 x 50 = 10000 record.

Quindi da questo risultato dobbiamo estrarre solo i record in cui t2.num1 E t2.num2 siano presenti nelle colonne di t1

Codice:
WHERE (
  t1.e1 = t2.num1 OR
  t1.e2 = t2.num1 OR
  t1.e3 = t2.num1 OR
  t1.e4 = t2.num1 OR
  t1.e5 = t2.num1 OR
  t1.e6 = t2.num1 OR
  t1.e7 = t2.num1 OR
  t1.e8 = t2.num1 OR
  t1.e9 = t2.num1 OR
  t1.e10 = t2.num1 OR
  t1.e11 = t2.num1 OR
  t1.e12 = t2.num1 OR
  t1.e13 = t2.num1 OR
  t1.e14 = t2.num1 OR
  t1.e15 = t2.num1 OR
  t1.e16 = t2.num1 OR
  t1.e17 = t2.num1 OR
  t1.e18 = t2.num1 OR
  t1.e19 = t2.num1 OR
  t1.e20 = t2.num1
) AND (
  t1.e1 = t2.num2 OR
  t1.e2 = t2.num2 OR
  t1.e3 = t2.num2 OR
  t1.e4 = t2.num2 OR
  t1.e5 = t2.num2 OR
  t1.e6 = t2.num2 OR
  t1.e7 = t2.num2 OR
  t1.e8 = t2.num2 OR
  t1.e9 = t2.num2 OR
  t1.e10 = t2.num2 OR
  t1.e11 = t2.num2 OR
  t1.e12 = t2.num2 OR
  t1.e13 = t2.num2 OR
  t1.e14 = t2.num2 OR
  t1.e15 = t2.num2 OR
  t1.e16 = t2.num2 OR
  t1.e17 = t2.num2 OR
  t1.e18 = t2.num2 OR
  t1.e19 = t2.num2 OR
  t1.e20 = t2.num2
)

Filtriamo ancora per limitare il range di date:

Codice:
AND giorno >= '2000-01-01' AND giorno <= '2011-12-31'

A questo punto abbiamo come risultato i record che ci interessano.

Adesso arriva l'ultima parte:

Codice:
GROUP BY num1,num2

GROUP BY permette di raggruppare i record in base ai campi specificati ( in realtà il CONCAT del post precedente non serve quindi l'ho tolto ). In pratica se due o più record hanno gli stessi valori di num1 e num2, vengono presi una sola volta. La comodità di questo è che così facendo il COUNT(*) all'inizio della query non conta più il totale dei record, ma i totali parziali di ogni raggruppamento.

Spero di essere riuscito a spiegarmi abbastanza bene
 
Ciao,
io proverei in questo modo sfruttando gli array:

PHP:
<?php

$conn = mysql_connect('localhost', 'root', '', 'database');
$db = mysql_select_db('database');

// estrai le coppie di numeri che vuoi cercare
$query = "SELECT e1,e2 FROM altratabella WHERE id IN(23,45,63,47,12,30)";
$res = mysql_query($query);

// crei un array con i risultati ottenuti
$coppieNumeri = array();
while ($row = mysql_fetch_array($res)) {
    $coppieNumeri[] = $row[0] . "," . $row[1];
}

// ricerca per data
$data1 = '2011-11-01';
$data2 = '2011-12-31';
$query = "SELECT * FROM tabella
                   WHERE data BETWEEN '$data1' AND DATE_ADD('$data2',INTERVAL 1 DAY)";
$res = mysql_query($query);
// crei un array con i risultati della ricerca per data
$arrayRisultati = array();
while ($row = mysql_fetch_array($res)) {
    $arrayRisultati[] = $row;
}

// cicli le coppie di numeri
foreach ($coppieNumeri as $value) {
    $ricorrenza = 0;
    // esplodi la stringa per ottenere i due numeri
    $coppia = explode(',', $value);
    // cicli l'array con i risultati della ricerca per data    
    foreach ($arrayRisultati as $value) {
        // verifichi se i numeri sono presenti nel risutltato
        if (in_array($coppia[0], $value) && in_array($coppia[1], $value)) {
            // li conti
            $ricorrenza++;
        }
    }
    // stampi il risultato
    echo $ricorrenza . " risultati per la coppia " . $coppia[0] . " e " . $coppia[1] . "<br/>";
}
?>
 
Ciao,
io proverei in questo modo sfruttando gli array:

PHP:
<?php

$conn = mysql_connect('localhost', 'root', '', 'database');
$db = mysql_select_db('database');

// estrai le coppie di numeri che vuoi cercare
$query = "SELECT e1,e2 FROM altratabella WHERE id IN(23,45,63,47,12,30)";
$res = mysql_query($query);

// crei un array con i risultati ottenuti
$coppieNumeri = array();
while ($row = mysql_fetch_array($res)) {
    $coppieNumeri[] = $row[0] . "," . $row[1];
}

// ricerca per data
$data1 = '2011-11-01';
$data2 = '2011-12-31';
$query = "SELECT * FROM tabella
                   WHERE data BETWEEN '$data1' AND DATE_ADD('$data2',INTERVAL 1 DAY)";
$res = mysql_query($query);
// crei un array con i risultati della ricerca per data
$arrayRisultati = array();
while ($row = mysql_fetch_array($res)) {
    $arrayRisultati[] = $row;
}

// cicli le coppie di numeri
foreach ($coppieNumeri as $value) {
    $ricorrenza = 0;
    // esplodi la stringa per ottenere i due numeri
    $coppia = explode(',', $value);
    // cicli l'array con i risultati della ricerca per data    
    foreach ($arrayRisultati as $value) {
        // verifichi se i numeri sono presenti nel risutltato
        if (in_array($coppia[0], $value) && in_array($coppia[1], $value)) {
            // li conti
            $ricorrenza++;
        }
    }
    // stampi il risultato
    echo $ricorrenza . " risultati per la coppia " . $coppia[0] . " e " . $coppia[1] . "<br/>";
}
?>


l'idea è proprio questa anche se tu l'hai strutturata diversamente da me, ma io ho quasi 5000 coppie da confrontare con 160000 righe su 20 colonne, non finisce mai di fare i cicli, ci mette troppo tempo....mi sa che sto cercando una soluzione impossibile.
 
Ok, ho dovuto risolvere diminuendo drasticamente il range di date, ma credo possa andare bene anche così.

Ulteriore problemino : ho aggiunto un altro campo alla tabella1 nella prima select :

$query = "SELECT id,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20 FROM TABELLA1 WHERE giorno >= '$date1' AND giorno <= '$date2'";

il campo in questione è il numero di ID.
Seguendo ciò che dice criric :

foreach ($arrayRisultati as $value) {
if (in_array($e1, $value) && in_array($e2, $value)) { // verifico se i numeri sono presenti nel risutltato
$coppia[$e1][$e2]++; // li conto
}
}

Ho ottenuto ciò che cercavo, ma ora vorrei anche sapere qual'è l'ultimo ID della coppia.
 
Ciao,

forse cosi:

foreach ($arrayRisultati as $key => $value) {

echo $key;
}

continuo col dire che secondo me BETWEEN è piu veloce di maggiore di... e minore di ...

poi magari la sparo grossa...
 
Ciao,

forse cosi:

foreach ($arrayRisultati as $key => $value) {

echo $key;
}

continuo col dire che secondo me BETWEEN è piu veloce di maggiore di... e minore di ...

poi magari la sparo grossa...



eccolo :

foreach ($arrayRisultati as $key => $value) {
if (in_array($e1, $value) && in_array($e2, $value)) { // verifico se i numeri sono presenti nel risultato
$idestr[$e1][$e2] = $arrayRisultati[$key][0];
$ritatt[$e1][$e2] = ( $idlastestr - $idestr[$e1][$e2] );
$coppia[$e1][$e2]++; // li conto
}
}


Proverò il BETWEEN molto presto, dato che la query iniziale è solo di prova.

Un ultima cosa che non centra nulla con questo fin'ora esposto e credo sono apposto :

In una query faccio l'ORDER BY di una sola colonna e va tutto bene, ma se lo faccio di 2 il risultato non è quello sperato :

SELECT * FROM TABELLA ORDER BY campo1,campo2,campo3 DESC

ho provato anche col CONCAT, ma non li ordina bene.
 

Discussioni simili