Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Perzentil von COUNT(DISTINCT) mit korreliertem WHERE funktioniert nur mit View (oder ohne DISTINCT)

Ich würde wahrscheinlich sagen, dass die Abfrage langsam ist, weil sie wiederholt auf die Tabelle zugreift, wenn der Trigger ausgelöst wird.

Ich bin kein SQL-Experte, aber ich habe versucht, eine Abfrage mit temporären Tabellen zusammenzustellen. Sie können sehen, ob es hilft, die Abfrage zu beschleunigen. Ich habe in meinem Codebeispiel unten andere, aber ähnlich klingende Spaltennamen verwendet.

BEARBEITEN : In meinem früheren Code war ein Berechnungsfehler. Jetzt aktualisiert.

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;

Dies bewirkt, dass es das Perzentil für jede Bewertungsgruppe aufzeichnet und dann schließlich nur tb1 aktualisiert Spalte mit den erforderlichen Daten, anstatt das Perzentil für jede Schülerzeile neu zu berechnen.

Sie sollten auch die Spalten s1 indizieren , s2 und s3 zur Optimierung der Abfragen für diese Spalten.

Hinweis:Bitte aktualisieren Sie die Spaltennamen gemäß Ihrem DB-Schema. Beachten Sie auch, dass jede Perzentilberechnung mit 100 multipliziert wurde da ich glaube, dass das Perzentil normalerweise so berechnet wird.