[英]Speed up MySQL query made in PHP
Say, i have a table a given here . 说,我在这里有一张桌子。 The table has the following structure (day of test, name of student, and marks obtained) 该表具有以下结构(测试日,学生姓名和获得的标记)
D NAME MARKS
2001-01-01 a 1
2001-01-04 a 4
2001-01-06 a 3
2001-01-08 a 3
2001-01-01 b 1
2001-01-10 b 15
2001-01-01 c 1
2001-01-06 c 2
2001-01-08 c 5
2001-01-10 c 7
I'd like to update the table by give 0 marks to those students who do not have an entry for each test. 我想通过给那些没有参加每个考试的学生的0分来更新表格。 The update table should look like this 更新表应如下所示
D NAME MARKS
2001-01-01 a 1
2001-01-02 a 0
2001-01-04 a 4
2001-01-06 a 3
2001-01-08 a 3
2001-01-02 a 0
2001-01-01 b 1
2001-01-02 b 0
2001-01-04 b 0
2001-01-06 b 0
2001-01-08 b 0
2001-01-10 b 15
2001-01-01 c 1
2001-01-02 c 2
2001-01-04 c 0
2001-01-06 c 0
2001-01-08 c 5
2001-01-10 c 7
So far, the only solution(very very slow query) i can figure out is: 到目前为止,我能搞清楚的唯一解决方案(非常慢的查询)是:
SELECT DISTINCT(D) FROM tableA;
SELECT DISTINCT(NAME) FROM tableA;
Using PHP, a sql query is made inside a nested loop 使用PHP,在嵌套循环内部进行SQL查询
INSERT IGNORE (D,NAME,MARKS)($D,$NAME,0);
However, the whole code takes too much time (in minutes) as there are more than 50k rows. 但是,整个代码需要花费太多时间(以分钟为单位),因为行数超过50k。
Any better suggestions? 有更好的建议吗?
Possibly do a cross join of the possible dates and possible names and left join that against the current results:- 可能会对可能的日期和可能的名称进行交叉连接,并且与当前结果保持联接: -
INSERT INTO A (D, name, marks)
SELECT Dates.D, Names.name, 0
FROM (SELECT DISTINCT D FROM A) Dates
CROSS JOIN (SELECT DISTINCT name FROM A) Names
LEFT OUTER JOIN A
ON Dates.D = A.D AND Names.name = A.name
WHERE A.name IS NULL
Note this does assume that at least one person has a mark for each day. 请注意,这确实假设每天至少有一个人有一个标记。
It would be better if you had a table of names and a table of dates, and just used the ids of these rows in the table A 如果你有一个名字表和一个日期表,那就更好了,只是在表A中使用了这些行的id
If you want to do this for a range of dates, even if nobody got a mark that day:- 如果你想在一系列日期中这样做,即使那天没有人拿到标记: -
INSERT INTO A (D, name, marks)
SELECT Dates.aDate, Names.name, 0
FROM
(
SELECT DATE_ADD('2001-01-01', INTERVAL units.i + tens.i * 10 + hundreds.i * 100 DAY) AS aDate
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
HAVING aDate BETWEEN '2001-01-01' AND '2001-12-30'
) Dates
CROSS JOIN
(
SELECT DISTINCT name
FROM A
) Names
LEFT OUTER JOIN A
ON Dates.aDate = A.D AND Names.name = A.name
WHERE A.name IS NULL
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.