2012-04-01 9 views
8

Mi sembra di essere un po 'bloccato. È una domanda abbastanza diretta.Aiuto mysql necessario per ottimizzare il gruppo in base alla query secondaria

Se eseguo le query separatamente, non è così lento, ma quando le combino è molto lento.

Non sono sicuro di come ottimizzarlo. Qualsiasi aiuto sarebbe molto apprezzato. In pratica, voglio solo mostrare più rimborsi. Quindi, dove faultid esiste più di una volta.

SELECT 
    r.* 
FROM 
    faultrefunds_v2 r 
WHERE 
    r.id IN (SELECT r1.id 
      FROM faultrefunds_v2 r1 
      GROUP BY faultid 
      HAVING count(r1.faultid) > 1); 

I risultati spiegano vengono sono stati allegato come un'immagine

enter image description here

+0

È r.id il primar tasto y? –

+0

sì, e faultid è la chiave esterna –

+0

Penso che la query che hai scritto non risponda alla domanda. Questo perché una volta che hai raggruppato per faultid, restituirai solo un r.id per questo faultid. –

risposta

1

immagino, questo si qualifica piuttosto come una ri-scrittura che come un ottimizzazione, ma questo è quello che vorrei provare, comunque:

SELECT 
    r.* 
FROM faultrefunds_v2 r 
WHERE EXISTS (
    SELECT * 
    FROM faultrefunds_v2 r1 
    WHERE r1.faultid = r.faultid 
    AND r1.id <> r.id 
); 
+0

ha funzionato anche questo. –

+0

perché è molto più veloce della query che ho scritto? sembrano abbastanza simili? –

+1

La tua query utilizza il raggruppamento, che è un'operazione relativamente costosa, per cominciare. Inoltre, una sottoquery di questo tipo dovrebbe eseguire la scansione dell'intera tabella per creare il set di righe con cui confrontarsi. La mia query, d'altra parte, usa un semi-join (nella forma del predicato 'EXISTS'). In un semi-join, le corrispondenze relative a una fine riga vengono ricercate non appena ne viene trovata almeno una, il che è probabile possa velocizzare notevolmente la query nei casi in cui esistono molte corrispondenze per alcune/la maggior parte delle righe. –

1

Credo che la query non è rispondere alla domanda. A quanto ho capito, per prima cosa dovresti avere tutti i faultid che hanno più di un id associato (riga nella tabella). E poi prendi tutte quelle righe (non solo l'errore).

Prova questo:

select * from faultrefunds_v2 
where faultId in (
    select faultId from faultrefunds_v2 
    group by faultId 
    having count(*) > 1 
) 
+0

Penso che questo sia un miglioramento della mia domanda, è più logico ed esplicativo. Ma è ancora piuttosto lento. dato +1 –

2

IN clausola il modo in cui è stato utilizzato sarebbe molto lenta, utilizzare JOIN invece:

SELECT r.* FROM ( 
    SELECT r1.id AS id 
    FROM faultrefunds_v2 r1 
    GROUP BY faultid 
    HAVING count(r1.faultid) > 1 
) AS ids 
LEFT JOIN faultrefunds_v2 AS r 
ON(ids.id = r.id) 
+0

questo funziona, è molto veloce. Puoi spiegare perché la clausola IN è lenta con il modo in cui l'ho usata così posso evitare di farlo di nuovo? –

+1

MySql di solito non indicizza gli elementi all'interno della clausola IN, quindi dovrebbe confrontare l'id di ogni riga nella tabella 'r' con tutti gli ID trovati nella query secondaria ogni volta. Nel mio metodo, MySql trova tutti gli ID appropriati una volta, quindi recupera molto rapidamente la riga completa per ciascun id nella query esterna utilizzando l'indice. – nobody

+0

Questa risposta è la risposta corretta lungo la risposta Andiry M laterale. Non posso accettare due risposte (anche se penso che sia possibile avere due risposte corrette ma diverse per la stessa domanda). –

Problemi correlati