Visualizzazione risultati 1 fino 6 di 6

Discussione: Estrarre specifiche righe da query

  1. #1
    zyro non è connesso Utente
    Data registrazione
    08-05-2010
    Messaggi
    105

    Question Estrarre specifiche righe da query

    Salve ragazzi, ho una domanda da porvi, magari voi riuscite a sbrogliare questa matassa mentale.

    Diciamo che ho una tabella con i dati di una serie di utenti, faccio uno schizzo veloce:

    ID Nome Cognome
    1 ...
    2 Anna Bianchi
    3 Stefania Rossi
    4 Silvia Rossi
    5 Claudio Gialli
    6 Franco Blu
    7 Piero Rossi
    8 Paolo Verdi
    9 Mauro Rossi
    10 Andrea Verdi
    11 Giuseppe Bianchi
    12 Rosa Rossi
    13 ...

    Partendo dall'id di un utente specifico (nell'esempio id 7) voglio estrapolare con la mia query la rispettiva riga, ma anche quella precedente e quella successiva a patto che abbiano un determinato dato in comune (nell'esempio in questione il cognome).
    Come potrei fare secondo voi?

  2. #2
    chrmar non è connesso Neofita
    Data registrazione
    10-04-2012
    Messaggi
    9

    Predefinito

    Ciao ti scrivo la seconda idea che mi è venuta in mente, la prima era di gestire un array con solo due query in modo da processarlo cercando la riga superiore e quella inferiore, ma mi è sembrato più complesso. Questo invece mi sembra più lungo ma più semplice da ideare.

    Io credo che potresti fare una cosa di questo genere

    1) Prendi dal DB con una SELECT la riga che ti interessa
    2) Processi quella riga, la metti in un array o in un oggetto
    3) Fai un'altra SELECT scegliendo tutti i campi con il criterio che ti interessa (es. WHERE cognome='Rossi') e con ID inferiori a quello del risultato precedente, e aggiungi un ORDER BY per metterli in ordine di ID
    4) Processi queste righe in un array o un oggetto
    5) Stampi l'ultimo elemento dell'array che sarà quello subito prima del tuo riferimento (es. id 7)
    6) Ultima SELECT per i campi con ID superiore, sempre ORDER BY per l'id
    7) Array o oggetto
    8) Stampi il primo elemento di questo array che sarà quello subito dopo il tuo riferimento (es. 7)


    Codice PHP:
    <?php
    $id
    = $_POST['id']; // Supponendo che prendi l'ID dalla richiesta di un form
    // $DBConn è l'oggetto che contiene la tua connessione al DB
    if($q = $DBConn->query("SELECT * FROM tabella WHERE ID='$id'")) { // Creo la prima query
    if($r=$q->fetch_object()) { // If perchè avrai una sola riga basandoti sull'ID quindi non serve fare un while
    print_r($r); // Debug per vedere se ti stampa un risultato, riga da rimuovere
    $index = $r->ID; // Prendo come riferimento l'ID del primo risultato, es.7
    $dato = $r->Cognome; // Prendo come riferimento il dato che mi interessa, ad esempio Cognome (Rossi)
    }
    }
    if(
    $q = $DBConn->query("SELECT * FROM tabella WHERE Cognome='$dato' AND ID<$index")) { // Creo la seconda query
    while($r=$q->fetch_assoc()) { // Creo un array associativo per i risultati dal DB con ID inferiore al richiesto
    $risinf[]=$r; // Compongo un array a parte per poterlo usare con tutti i dati
    }
    $inferiore = end($risinf); // Quando ha finito, prendo l'ultimo elemento
    // Che è la riga subito prima del mio indice, perchè ho fatto ORDER BY quindi l'ultimo elemento è quello con ID maggiore di tutti
    echo "La riga inferiore è:<br />";
    print_r($inferiore);
    }
    // Poi faccio il contrario nella query
    if($q = $DBConn->query("SELECT * FROM tabella WHERE Cognome='$dato' AND ID>$index")) { // Creo la terza query
    while($r=$q->fetch_assoc()) {
    $rissup[]=$r; // Righe superiori
    }
    $superiore = $rissup[0]; // Prendo il primo elemento cioè la prima riga che è quindi la prima subito dopo il mio index
    echo "<br />La riga superiore è:<br />";
    print_r($superiore);
    }
    ?>
    Sto pensando ad un'altra soluzioni più semplice usando due foreach per ciclare un array con tutti i dati basati sul cognome e prendere quindi più facilmente l'elemento precedente e quello successivo, ma mi sta richiedendo un po' di ragionamento. Se ci riesco ti rispondo nuovamente.
    Ultima modifica di chrmar : 16-11-2016 alle ore 16.51.52

  3. #3
    zyro non è connesso Utente
    Data registrazione
    08-05-2010
    Messaggi
    105

    Predefinito

    Ciao chrmar e grazie per il supporto.
    Avevo iniziato a pensare all'idea che mi hai proposto, ma l'ho scartata quasi subito per il dispendio di energie che richiederebbe tale soluzione.
    Quello che ho indicato sopra è chiaramente un esempio semplificato della tabella su cui devo operare, nella realtà si prospettano milioni di righe di dati da dover analizzare, quindi ciclare gli stessi risultati per 3 volte non è forse il massimo di ottimizzazione.
    Prima di aprire il post stavo cercando qualcosa con le subquery almeno per limitare il codice visivo. Se una subquery generasse un id aggiuntivo per i suoi risultati forse potrei sfruttare quello nella query principale, ma a memoria non credo sia così.

    Codice PHP:
    "SELECT * FROM (SELECT idsubquery AS idsub, * FROM tabella WHERE id=7) WHERE (idsub=7-1 OR idsub=7 OR idsub=7+1)"
    In alternativa stavo pensando di aggiungere un nuovo dato con un id progressivo per ogni elemento. Nell'esempio Piero Rossi che è l'elemento da cui parto avrebbe il numero 4 poiché* è il quarto Rossi in elenco. Sfruttando quello non sussisterebbe nessun problema perché mi passerei anche quel dato e il gioco è fatto, ma vorrebbe dire anche rimettere mano ad altri 10 script, cosa scocciante alquanto, oltre che poco elegante.

  4. #4
    chrmar non è connesso Neofita
    Data registrazione
    10-04-2012
    Messaggi
    9

    Predefinito

    Per quanto riguarda le subquery, qualcuno fa qualcosa di questo genere, guardando su internet, ti riporto qualcosa che potrebbe essere di aiuto.
    Ho cercato "mysql selecting previous and following row of an element"... magari trovi qualcosa che ti può aiutare.
    Codice PHP:
    (select min(id) from foo where id > 4) and (select max(id) from foo where id < 4)
    SELECT * FROM tabella WHERE ID = (SELECT min(ID) FROM tabella WHERE ID > $id ORDER BY ID LIMIT 1) AND (SELECT max(ID) FROM tabella WHERE ID < $id ORDER BY ID LIMIT 1)
    Codice PHP:
    select * from tabella
    where
    (
    id = IFNULL((select min(id) from tabella where id > 4),0)
    or
    id = IFNULL((select max(id) from tabella where id < 4),0)
    )
    Non sono un esperto di subqueries quindi non ho verificato la loro funzionalità. a livello teorico mi sembrano sensate comunque.
    Un altra idea che ho trovato era di usare un UNION SELECT o qualcosa del genere
    Codice PHP:
    (SELECT * FROM Tabella WHERE id < 3 ORDER BY id DESC LIMIT 1)
    UNION
    (SELECT * FROM Tabella WHERE id > 3 ORDER BY id LIMIT 1)
    E magari agire su delle unioni di dati e pescare quindi il tutto da qui... Tipo che so
    Codice PHP:
    (SELECT * FROM Tabella WHERE ID=$id) UNION (SELECT * FROM Tabella WHERE ID<$id ORDER BY ID DESC LIMIT 1) UNION (SELECT * FROM Tabella WHERE ID>$id ORDER BY ID LIMIT 1)
    Non ho idea se questa funzioni cioè l'ho pensata alcuni minuti e mi viene da scrivertela così in modo grezzo, l'ho provata un attimo e mi sembra ok, ma dovrai adattarla, prova a vedere se con questo magari ti viene qualche idea, in genere non faccio query complesse quindi probabilmente c'è qualcosa di sbagliato. In pratica cerco di unire le query selezionando di volta in volta dei dati precisi ma non so se sia esattamente questo il modo in cui vuoi farlo. Ad ogni modo credo che anche facendo così non sia molto diverso che da fare 3 query separate, però vedi tu come ti sembra meglio, per il discorso dei milioni di dati al limite potresti usare dei LIMIT per non dover gestire risultati troppo grossi... Dipende quanta roba devi tirare fuori di volta in volta... Se sai che prendi solo poche righe alla volta ti conviene usare un LIMIT a mio avviso.

  5. #5
    zyro non è connesso Utente
    Data registrazione
    08-05-2010
    Messaggi
    105

    Predefinito

    Neanche io sono un grande esperto di subquery, per questo non so se generano o meno un id interno per ordinare i risultati. Cioè la logica mi fa pensare che dovrebbe esserci un'indicizzazione perché la subquery crea una tabella virtuale con i risultati da cui la query originale preleva i suoi dati, però non so proprio come estrapolarne questo indice e nelle mie ricerche ho trovato ben poco che possa rispondere a questo dubbio.

    Beh in totale devo riuscire a estrarre 5 risultati, quello passato tramite richieste più i due precedenti e i due successivi affini all'elemento cercato (cognome Rossi nell'esempio)

    Forse così potrebbe essermi utile, dovrò testarla
    Codice PHP:
    (SELECT * FROM tabella WHERE id < 7 AND cognome = Rossi ORDER BY id DESC LIMIT 1)
    UNION
    (SELECT * FROM Example WHERE id = 7)
    UNION
    (SELECT * FROM tabella WHERE id > 7 AND cognome = Rossi ORDER BY id LIMIT 1)
    Appena finisco di sistemare un altro script a cui ho dato precedenza perché a questo mi son bloccato lo provo, grazie dell'aiuto

  6. #6
    zyro non è connesso Utente
    Data registrazione
    08-05-2010
    Messaggi
    105

    Predefinito

    Scusate per il ritardo nella risposta, ma il mio PC era letteralmente esploso per un condensatore fuso (per fortuna ho il vizio di farmi backup e salvare dati esternamente) Fine OT

    Lo script funziona abbastanza bene, mi è dispiaciuto non essere riuscito a dargli un ordinamento esterno alla UNION perché ho scelto di prelevare i 2 record precedenti e successivi, ma ho ovviato duplicando nuovamente altre due select. Grazie dell'aiuto chrmar

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •