sql >> Base de Datos >  >> RDS >> Mysql

percentil por COUNT(DISTINCT) con DONDE correlacionado solo funciona con una vista (o sin DISTINCT)

Probablemente diría que la consulta es lenta porque accede repetidamente a la tabla cuando se activa el activador.

No soy un experto en SQL, pero he intentado armar una consulta usando tablas temporales. Puede ver si ayuda a acelerar la consulta. He usado nombres de columna que suenan diferentes pero similares en mi ejemplo de código a continuación.

EDITAR: Hubo un error de cálculo en mi código anterior. Actualizado ahora.

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;

Lo que esto hace es que registra el percentil para cada grupo de puntuación y luego, finalmente, solo actualiza el tb1 columna con los datos requeridos en lugar de volver a calcular el percentil para cada fila de estudiante.

También debe indexar las columnas s1 , s2 y s3 por optimizar las consultas en estas columnas.

Nota:actualice los nombres de las columnas de acuerdo con su esquema de base de datos. También tenga en cuenta que cada cálculo de percentil se ha multiplicado por 100 ya que creo que el percentil generalmente se calcula de esa manera.