sql >> Database >  >> RDS >> Mysql

percentiel door COUNT(DISTINCT) met gecorreleerd WHERE werkt alleen met een weergave (of zonder DISTINCT)

Ik zou waarschijnlijk zeggen dat de query traag is omdat deze herhaaldelijk de tabel opent wanneer de trigger wordt geactiveerd.

Ik ben geen SQL-expert, maar ik heb geprobeerd een query samen te stellen met behulp van tijdelijke tabellen. U kunt zien of het helpt om de zoekopdracht te versnellen. Ik heb verschillende maar vergelijkbaar klinkende kolomnamen gebruikt in mijn codevoorbeeld hieronder.

BEWERK: Er zat een rekenfout in mijn eerdere code. Nu bijgewerkt.

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;

Wat dit doet, is dat het het percentiel voor elke scoregroep registreert en vervolgens de tb1 bijwerkt. kolom met de vereiste gegevens in plaats van het percentiel voor elke leerlingrij opnieuw te berekenen.

U moet ook kolommen s1 index indexeren , s2 en s3 voor het optimaliseren van de zoekopdrachten op deze kolommen.

Opmerking:werk de kolomnamen bij volgens uw db-schema. Merk ook op dat elke percentielberekening is vermenigvuldigd met 100 omdat ik geloof dat dat percentiel meestal op die manier wordt berekend.




  1. sla kopiëren naar tmp-tabel op schijf over mysql

  2. Herhaalde resultaten verwijderen uit MySQL-query

  3. Converteer BufferedInputStream naar afbeelding

  4. PHP MySQL instellen Verbindingstime-out