Mysql
 sql >> Database >  >> RDS >> Mysql

percentile per COUNT(DISTINCT) con correlato WHERE funziona solo con una vista (o senza DISTINCT)

Probabilmente direi che la query è lenta perché accede ripetutamente alla tabella quando viene attivato il trigger.

Non sono un esperto di SQL ma ho provato a mettere insieme una query utilizzando tabelle temporanee. Puoi vedere se aiuta ad accelerare la query. Ho usato nomi di colonne dal suono diversi ma simili nel mio esempio di codice di seguito.

MODIFICA : Si è verificato un errore di calcolo nel mio codice precedente. Aggiornato ora.

SELECT COUNT(id) INTO @no_of_attempts from tb2;

-- DROP TABLE IF EXISTS S1Percentiles;
-- DROP TABLE IF EXISTS S2Percentiles;
-- DROP TABLE IF EXISTS S3Percentiles;

CREATE TEMPORARY TABLE S1Percentiles (
    s1 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);

CREATE TEMPORARY TABLE S2Percentiles (
    s2 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);

CREATE TEMPORARY TABLE S3Percentiles (
    s3 FLOAT NOT NULL,
    percentile FLOAT NOT NULL DEFAULT 0.00
);



INSERT INTO S1Percentiles (s1, percentile)
    SELECT A.s1, ((COUNT(B.s1)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s1 from tb2) A
    INNER JOIN tb2 B
    ON B.s1 <= A.s1
    GROUP BY A.s1;

INSERT INTO S2Percentiles (s2, percentile)
    SELECT A.s2, ((COUNT(B.s2)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s2 from tb2) A
    INNER JOIN tb2 B
    ON B.s2 <= A.s2
    GROUP BY A.s2;

INSERT INTO S3Percentiles (s3, percentile)
    SELECT A.s3, ((COUNT(B.s3)/@no_of_attempts)*100)
    FROM (SELECT DISTINCT s3 from tb2) A
    INNER JOIN tb2 B
    ON B.s3 <= A.s3
    GROUP BY A.s3;

-- select * from S1Percentiles;
-- select * from S2Percentiles;
-- select * from S3Percentiles;

UPDATE tb1 A
    INNER JOIN
    (
    SELECT B.tb1_id AS id, (C.percentile + D.percentile + E.percentile) AS sum FROM tb2 B
        INNER JOIN S1Percentiles C
        ON B.s1 = C.s1
        INNER JOIN S2Percentiles D
        ON B.s2 = D.s2
        INNER JOIN S3Percentiles E
        ON B.s3 = E.s3
    ) F
    ON A.id = F.id

    SET A.sum = F.sum;

-- SELECT * FROM tb1;

DROP TABLE S1Percentiles;
DROP TABLE S2Percentiles;
DROP TABLE S3Percentiles;

Ciò che fa è che registra il percentile per ciascun gruppo di punteggio e quindi alla fine aggiorna semplicemente il tb1 colonna con i dati richiesti invece di ricalcolare il percentile per ogni riga studente.

Dovresti anche indicizzare le colonne s1 , s2 e s3 per ottimizzare le query su queste colonne.

Nota:aggiorna i nomi delle colonne in base al tuo schema db. Tieni inoltre presente che ogni calcolo percentile è stato moltiplicato per 100 poiché credo che il percentile venga solitamente calcolato in questo modo.