sql >> Databasteknik >  >> RDS >> Mysql

percentil med COUNT(DISTINCT) med korrelerad WHERE fungerar bara med en vy (eller utan DISTINCT)

Jag skulle förmodligen säga att frågan är långsam eftersom den upprepade gånger kommer åt tabellen när utlösaren aktiveras.

Jag är ingen SQL-expert men jag har försökt sätta ihop en fråga med hjälp av tillfälliga tabeller. Du kan se om det hjälper att påskynda frågan. Jag har använt olika men liknande klingande kolumnnamn i mitt kodexempel nedan.

REDIGERA: Det fanns ett beräkningsfel i min tidigare kod. Uppdaterad nu.

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;

Vad detta gör är att det registrerar percentilen för varje poänggrupp och sedan till sist bara uppdaterar tb1 kolumnen med de nödvändiga uppgifterna istället för att räkna om percentilen för varje elevrad.

Du bör också indexera kolumnerna s1 , s2 och s3 för att optimera frågorna i dessa kolumner.

Obs:Uppdatera kolumnnamnen enligt ditt db-schema. Observera också att varje percentilberäkning har multiplicerats med 100 eftersom jag tror att percentilen brukar beräknas på det sättet.




  1. SQL välj element där summan av fältet är mindre än N

  2. Använd PostgreSQL SSL-anslutning i rost med självsignerade certifikat

  3. Oracle-stödda versioner Matrix

  4. Hur man ändrar standardvärdet för en kolumn med hjälp av en procedur