0

我有一个奇怪的,我不知道这是我的语法(看起来很简单)还是一个错误(或者只是不受支持)。

这是我的查询有效但不必要的慢:

UPDATE table1 
    SET table1column1 = 
        (SELECT COUNT(DISTINCT table2column1) FROM table2view WHERE table2column1 <= (SELECT table2column1 FROM table2 WHERE table2.id = table1.id) )
        / 
        (SELECT COUNT(DISTINCT table2column1) FROM table2) 

       + (SELECT COUNT(DISTINCT table2column2) FROM table2view WHERE table2column2 <= (SELECT table2column2 FROM table2 WHERE table2.id = table1.id) ) 
        / 
        (SELECT COUNT(DISTINCT table2column2) FROM table2) 

       + (SELECT COUNT(DISTINCT table2column3) FROM table2view WHERE table2column3 <= (SELECT table2column3 FROM table2 WHERE table2.id = table1.id) ) 
        / (SELECT COUNT(DISTINCT table2column3) FROM table2);

它只是删除重复项的三个百分位数(table2column1、table2column2 和 table2column3)的总和。

这就是它变得奇怪的地方。我必须为此使用一个视图来处理子查询,WHERE否则它只会UPDATE显示 的第一行table1,并将其余行设置table1column10。那table2viewtable2. 是的,很奇怪。

如果我不使用DISTINCT,我可以在没有视图的情况下做到这一点。那有意义吗? 注意:我必须有,DISTINCT因为我有很多重复项。

我试着SELECT只从视图中制作它,但这减慢了它的速度。

有谁知道问题是什么以及返工这个查询的最佳方法,所以它不需要这么长时间?它在 aTRIGGER中,并且更新的数据非常按需。

提前谢谢了!

细节

我正在 phpMyAdmin 的命令行中测试速度。

我很确定降级来自视图,因为视图越多,我使用的实际表越少,它变得越慢。

当我做一个没有DISTINCT的时候,它的速度很快。

仅适用于视图?

好的,所以我只是设置了table2. 我首先尝试执行原始查询,用副本替换视图。不去。

我尝试使用副本而不是视图来执行以下查询。不去。

希望这些常量的引入能更好地展示我正在尝试做的事情。

SET @table2column1_distinct_count = (SELECT COUNT(DISTINCT table2column1) FROM table2);
SET @table2column2_distinct_count = (SELECT COUNT(DISTINCT table2column2) FROM table2);
SET @table2column3_distinct_count = (SELECT COUNT(DISTINCT table2column3) FROM table2);
UPDATE table1, table2
    SET table1.table1column1 = (SELECT COUNT(DISTINCT table2column1) FROM  table2view WHERE table2column1 <= table2.table2column1) / @table2column1_distinct_count 
    + (SELECT COUNT(DISTINCT table2column2) FROM  table2view WHERE table2column2 <= table2.table2column2) / @table2column2_distinct_count 
    + (SELECT COUNT(DISTINCT table2column3) FROM  table2view WHERE table2column3 <= table2.table2column3) / @table2column3_distinct_count 
        WHERE table1.id = table2.id;

同样,当我使用table2而不是 时table2view,它只会正确更新第一行并设置所有其他行的 table1.table1column1 = 0

数学

我正在尝试将= 设置为、和bytable1.table1column1的百分位数之和。table2column1table2column2table2column3id

我通过(计算 a table2columnX<= 到 current的不同值)/(不同stable2columnX的总数)来做一个百分位数。table2columnX

DISTINCT用来摆脱过多的重复。

看法

这是SELECT视图。这有帮助吗?

CREATE VIEW myTable.table2view AS SELECT
    table2.table2column1 AS table2column1,
    table2.table2column2 AS table2column2,
    table2.table2column2 AS table2column3,
FROM table2
GROUP BY table2.id;

GROUP BY视图中是否有什么特别之处SELECT可以使这项工作(我没有看到)?

4

1 回答 1

0

我可能会说查询很慢,因为它在触发器触发时重复访问表。

我不是 SQL 专家,但我尝试使用临时表来组合查询。您可以查看它是否有助于加快查询速度。我在下面的代码示例中使用了不同但相似的列名。

编辑:我之前的代码中有一个计算错误。现在更新了。

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;

它的作用是记录每个分数组的百分位数,然后最后只tb1用必要的数据更新列,而不是重新计算每个学生行的百分位数。

您还应该索引列s1s2s3优化对这些列的查询。

注意:请根据您的数据库架构更新列名。另请注意,每个百分位数计算都已乘以,100因为我相信百分位数通常是这样计算的。

于 2012-12-31T06:51:11.753 回答