2009-10-21 36 views
-1

以下查询挂起:(尽管子查询单独执行很好)为什么我的MySQL查询使用子选择挂起?

我不知道如何使解释表看起来没问题。如果有人告诉我,我会清理它。

select 
sum(grades.points)) as p, 
from assignments 
left join grades using (assignmentID) 
where gradeID IN 

(select grades.gradeID 
from assignments 
left join grades using (assignmentID) 
where ... grades.date <= '1255503600' AND grades.date >= '984902400' 
group by  assignmentID order by grades.date DESC); 

我认为问题是与第一年级的表...类型ALL与许多行似乎是原因..一切都索引。

我上传了表格作为图像。无法得到正确的格式: http://imgur.com/AjX34.png

一个评论者想全where子句:

explain extended select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
where gradeID IN 
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC); 
+0

有问题吗? – jjclarkson 2009-10-21 16:21:47

+0

请使用语法hilighting和结构的代码,我不能读取这个:( – 2009-10-21 16:25:47

+0

我修复了查询,但我不知道如何让表格格式。我需要使用html表格标签? – Stephane 2009-10-21 16:33:43

回答

1

假设你使用一个真正的数据库(即,除了MySQL的任何数据库,但我会用的Postgres为例)要做到这一点查询:

SELECT * FROM ta WHERE aid IN (SELECT subquery) 

一个真正的数据库会看着子查询,并估计其行数:

  • 如果行数小(比如,超过几百万以下)

它会运行子查询,然后建立一个ids内存中的哈希,这也使得它们是唯一的,这是IN()的一个特性。

然后,如果从ta拉出的行数是ta的一小部分,它将使用合适的索引来拉行。或者,如果选择了表格的主要部分,它将完全扫描它,并查找散列中的每个ID,这非常快。

  • 然而,如果子查询的行数是相当大的

数据库可能会重写它作为一个合并连接,增加了排序+独有的子查询。

但是,您正在使用MySQL。在这种情况下,它不会执行任何操作(它将为表格的每一行重新执行子查询),因此需要1000年时间。抱歉。

0

真的是没有足够的信息来回答你的问题,你已经把一个...在where子句的中间是很奇怪的。涉及的表格有多大,索引是多少?

话虽如此,如果在一个条款中有太多的条款,你可以看到严重退化的性能。 用正确的连接代替使用。

对于初学者,不使用in子句中的表as_types。左参加它没有任何目的,所以摆脱它。

剩下的来自外部查询只具有作业和成绩表条款。显然,修改分配属于外部查询的where子句。你应该将所有的成绩=任何转换成左连接的成绩条款。

+0

表格真的很大(成千上万到数十万)。索引是关于我在where子句中使用的所有内容 ...代替5或6不相关的地方,我认为会把它弄乱,我会将它追加到最后。 – Stephane 2009-10-21 16:44:37

+0

我一直在试图找到如何去做你的建议: 从表右连接选择东西(选择的东西),但我不明白如何将括号中的内容与外部查询相关联。 – Stephane 2009-10-21 17:04:57

+0

这可能不是一个正确的连接,它可能是一个左连接。 – stevedbrown 2009-10-21 17:19:01

0

如果当它被单独执行你的子查询执行罚款,然后尝试使用JOIN,而不是像这样:

select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
join 
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC) using (gradeID); 
1

超级乱,但:(大家的帮助感谢)

SELECT * 
    FROM grades 
    LEFT JOIN assignments ON grades.assignmentID = assignments.assignmentID 
    RIGHT JOIN (

    SELECT g.gradeID 
FROM assignments a 
LEFT JOIN grades g 
USING (assignmentID) 
WHERE a.classID = '7815' 
AND (
a.type =30170 
) 
AND g.contactID =7141 
    g.points 
REGEXP '^[-]?[0-9]+[-]?' 
AND g.points != '-' 
AND g.points != '' 
AND (
g.pointsposs IS NULL 
OR g.pointsposs = '' 
) 
AND g.date <= '1255503600' 
AND g.date >= '984902400' 
GROUP BY assignmentID 
ORDER BY g.date DESC 
) AS t1 ON t1.gradeID = grades.gradeID 
0

该查询有点难以遵循,但我怀疑子查询根本没有必要。 好像您的查询基本上是这样的:

SELECT FOO() 
FROM assignments LEFT JOIN grades USING (assignmentID) 
WHERE gradeID IN 
(
SELECT grades.gradeID 
FROM assignments LEFT JOIN grades USING (assignmentID) 
WHERE your_conditions = TRUE 
); 

但是,你没有做任何事情在子查询的WHERE子句中真正看中的。 我怀疑更多的东西

SELECT FOO() 
FROM assignments LEFT JOIN grades USING (assignmentID) 
GROUP BY groupings 
WHERE your_conditions_with_some_tweaks = TRUE; 

会工作得很好。

如果我在这里失去了一些关键的逻辑请评论回来,我会编辑/删除这个帖子。