• ModSenior

    Ah scusa avevo capito male ciò che chiedevi, prova cosi:
    SELECT * FROM tabella GROUP BY id HAVING count(id) = (SELECT count(id) AS n_trovati FROM tabella GROUP BY id ORDER BY n_trovati DESC LIMIT 1)


  • User Attivo

    Funziona:D... grazie...

    Tanto per capire se ho capito...

    la prima query come prima grazie ad having va a vedere quante righe ci sono in ogni gruppo

    La seconda salva in n_trovati gli id che count conta sempre suddividendoli in gruppi. Con order by n_trovati desc limit 1 li ordina in ordine decrescente e seleziona solo l'ultimo che inevitabilmente è il più grande

    Mettendole assieme le due e usando la seconda come parametro delle query having, seleziono l'id trovato in più righe, che è quello che a me interessa..

    Ho capito giusto cosa fa?

    Poi ho un dubbio su un ultima ottimizzazione, ci starebbe bene un order by id LIMIT 1 anche alla fine dopo la seconda query (comanderebbe praticamente la prima) tanto per non rischiar di far girare a vuota o più del necessario la prima query? O scasserebbe tutto??
    tipo:
    SELECT * FROM tabella GROUP BY id HAVING count(id) = (SELECT count(id) AS n_trovati FROM tabella GROUP BY id ORDER BY n_trovati DESC LIMIT 1) ORDER BY id LIMIT 1

    Un ultima cosa, non avevo mai concepito l'idea di utilizzar una query come parametro di una query.. mi hai aperto un mondo... forse in futuro mi risparmierò un sacco di tempo e di codice... grazie


  • ModSenior

    Si hai capito bene su come funziona.
    Se hai 2 id che sono presenti lo stesso numero di volte, ed inserisci il limit non otterrai ciò che volevi.
    Inserire quel limit per ottimizzare la query è, a mio avviso, inutile in quanto deve comunque controllare l'intera tabella per effettuare il raggruppamento, una cosa che potresti fare per aumentare la velocità di lettura della query è mettere il campo id come indice.
    Ho fatto un test in locale, con 5000 dati inseriti nella tabella senza indice la query impiega al massimo 0.0092 sec, mentre utilizzando l'indice impiega meno di metà del tempo. I tempi li ho presi con la cache disabilitata, per cui direi che non dovresti avere grandissimi problemi.

    Le subquery esistono da parecchio tempo in MySQL in alcuni casi possono tornare utili.


  • User Attivo

    Grazie mille... capito, come indice ho usato un id_riga in autoincrement, forse però a questo punto non serve a un tubo... magari lo levo e metto l'id ricercato?

    Per non rischiar di fare impiegare troppo tempo alla query nel cercar tra troppe righe ho anche pensato, di chiamarla "il più visto della settimana" cosi cancello man mano tutti i record che son li da più di 7 giorni, e salvo non mi facciano centinaia di migliaia di visualizzazioni al giorno (magari accadesse...) non dovrei correre il rischio di tempi troppo lunghi, anche se inserendo una riga per ogni visualizzazione sicuramente ci saranno molte record duplicati.


  • ModSenior

    No, non devi creare un nuovo campo come indice ma impostare quello che viene poi utilizzato nella query.


  • User Attivo

    Un ultimo dubbio...

    Ho provato a impostare l'id come primary key , ma non gli piace, credo proprio perche id può essere duplicato.

    Fatto cosi
    CREATE TABLE IF NOT EXISTS animali_video_vis_settimana (
    id_video int(11) NOT NULL,
    id_animale int(11) NOT NULL,
    video varchar(255) NOT NULL,
    data_ins varchar(255) NOT NULL,
    PRIMARY KEY id_video (id_video)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    Dice cosi
    Errore

    Query SQL:

    --
    -- Dump dei dati per la tabella animali_video_vis_settimana

    INSERT INTO animali_video_vis_settimana ( id_video , id_animale , video , data_ins )
    VALUES ( 1, 13, 'EVXz3i9GVqc', '1343256423' ) , ( 1, 13, 'EVXz3i9GVqc', '1343256431' ) , ( 1, 13, 'EVXz3i9GVqc', '1343256440' ) , ( 4, 13, 'PPqpNv6m1To', '1343317797' ) , ( 4, 13, 'PPqpNv6m1To', '1343317804' ) , ( 4, 13, 'PPqpNv6m1To', '1343317808' ) , ( 4, 13, 'PPqpNv6m1To', '1343317844' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341072' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341077' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341090' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341093' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341108' ) , ( 6, 13, 'dXHUVw_QHMw', '1343341114' ) ;

    Messaggio di MySQL: Documentazione
    #1062 - Duplicate entry '1' for key 1

    Basta key senza primary???


  • ModSenior

    Si devi mettere come semplice key, visto che sono valori ripetuti.


  • User Newbie

    Ciao, cercando sul forum ho trovato questo messaggio che "penso" possa aiutarmi.
    Mi trovo in una situazione dove a fronte di una ricerca devo restituire un risultato composto da una struttura e più partenze.
    Nel dettaglio:
    ho 2 tabelle una prodotti e una servizi. Dal form di ricerca cerco tutti gli hotel che sono in una destinazione che hanno delle partenze dal ....
    la query di risposta che ho scritto è così composta:

    SELECT * FROM catalog_service AS s INNER JOIN catalog AS p ON s.lid=p.lid WHERE s.departure >='datapartenza' AND p.template=4 ORDER BY s.sid DESC LIMIT 0,10;

    La query funziona ma così nel successivo ciclo while ,mi restituisce lo stesso hotel ripetutto per il numero di partenze, io invece vorrei avere solo 1 hotel con tutte le sue partenze.
    Pensavo che la soluzione fosse nel GROUP by e ho preso spunto dalla vostra risposta....ma non ci ho capito niente.

    Ciao e Grazie


  • User Attivo

    Ciao,
    riapro questo post perchè ho una piccolissima variante da fare sulla soluzione dell'altra volta.

    Vorrei non più solo il più visto, ma "i più visti", esempio i 5 più visti di questa settimana

    Ho subito pensato bastasse cambiare il limit a questa query e fare un while..
    SELECT * FROM tabella GROUP BY id HAVING count(id) = (SELECT count(id) AS n_trovati FROM tabella GROUP BY id ORDER BY n_trovati DESC LIMIT 1)

    Ma a mysql non piace... dice...
    #1242 - Subquery returns more than 1 row

    Come ne esco??
    Si può fare con questo tipo di query?

    Ciao
    Grazie


  • ModSenior

    Togli il group by dalla subquery e funziona, anche perchè non credo proprio che ti serva visto che usa l'id.


  • User Attivo

    Non mostra piu nulla senza group
    $query_piu_visti = "SELECT * FROM ".$prefix."piu_visti_sett GROUP BY id_news HAVING count(id_news) = (SELECT count(id_news) AS n_trovati FROM ".$prefix."piu_visti_sett ORDER BY n_trovati DESC LIMIT 5)";
    //echo $query_piu_visti;
    $piu_visti_query = mysql_query($query_piu_visti, $db);
    while($row_piu_visti = mysql_fetch_array($piu_visti_query)){


  • ModSenior

    Ma a cosa ti serve la subquery in questo caso? Perchè non ordini usando il count e applichi un limit?


  • User Attivo

    Fondamentalmente perche ora non so come toglierla...

    Cioè dopo having uguale cosa metto?

    SELECT * FROM ".$prefix."piu_visti_sett GROUP BY id_news HAVING count(id_news) =..........


  • ModSenior

    Puoi postare la struttura di piu_visti_sett?


  • User Attivo

    Fatta cosi semplice semplice
    CREATE TABLE IF NOT EXISTS streaming_up_tv_piu_visti_sett (
    id_news int(11) NOT NULL,
    titolo varchar(255) NOT NULL,
    img varchar(255) NOT NULL,
    data_ins varchar(255) NOT NULL,
    KEY id_news (id_news)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

    Poi sulla pagina di output del singolo post inserisco e cancello i più vecchi di una settimana


  • User Attivo

    E' davvero cosi un casino???

    Di solito rispondi molto veloce...


  • User Attivo

    Ho provato cosi
    SELECT count(id_news) AS n_trovati, id_news, titolo, img FROM ".$prefix."piu_visti_sett GROUP BY id_news ORDER BY n_trovati DESC LIMIT 5

    Cioè togliendo la parte a sinistra di having ed effettivamente ne mostra 5 e non sembra lamentarsi più di tanto...

    Ho però qualche dubbio sull'ordinamento, cioè sul fatto che siano effettivamente i 5 più visitati... Secondo voi??? Saranno giusti con la query scritta cosi?


  • User Attivo

    Ciao,
    vorrei riaprire questa discussione perche ho un altra query un pò diversa da quelle che si usano di solito. E mi sembra cosa carina dare in un solo posto diverse risposte a problemi particolari...

    Ho un db con questa struttura
    id_campagna
    clicks_rimanenti
    clicks_consumati

    Vorrei estrarre dal database l'id di una campagna che non ha ancora esaurito i clicks.
    Si potrebbe fare in phpcon diverse query, ma sono sicuro (anche se non l'ho mai usato) che esiste un modo per farlo usando la clausola where di mysql.

    Qualcosa tipo
    SELECT * FROM campagne WHERE clicks < clicks_consumati

    dove click e clicks_consumati sono 2 campi mysql e non variabili php ( forse funziona già cosi come l'ho scritta)

    Secondo voi funziona? Altrimenti come si scrive?