在主查询中使用子查询结果的Mysql

时间:2012-02-29 04:48:28

标签: mysql

基本上,我想做的是让所有孩子在某个出生年份内进入另一张桌子。所以我有两张桌子。让我们说这是一张学校的桌子

学校

school_id
child_id

儿童

child_id
birth_year
name
etc

我的第一次尝试是使用子查询,就像这样

SELECT *, (SELECT COUNT(*) FROM school LEFT JOIN children ON school.child_id = children.child_id) as total FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year

这个查询的问题是子查询将在整个记录中运行,所以如果我有1000条记录,我认为查询(和子查询)将在birth_year分组之前运行1000次,这很慢,几乎是3 500个样本数据为-5秒。

所以为了优化它,我正在这样做。

使用PHP的递归查询

首先,获得所有在校儿童的出生年份。所以我要查询类似

的内容
SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id

它将返回

之类的数据
birth_year
==========
2009
2010
2011

我将在PHP的另一个查询中使用(假设我将结果存储在$ row变量中)

foreach ($row as $r){
    $new_array[] = count($this->db->get_child_data($r->birth_year)); //this is pseudocode only, to get the number of children data who have birth_year of 2009-2011
}

虽然它会运行额外的三个查询,但这非常快,因为计数很简单。 500个样本数据只需不到0.5秒。

但是,我想知道是否有任何优化方法?或者更好的是,有没有办法在具有类似性能的单个查询中执行此操作?

我正在努力做到这一点,但它最终会变得非常缓慢而且会导致我的WAMP崩溃。

SELECT * FROM children WHERE birth_year IN (SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id )

子查询

SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id

正确单独运行并快速返回

2009,2010,2011

当我查询

SELECT * FROM children WHERE birth_year IN (2009,2010,2011)

它也很快,所以我很困惑,为什么当我加入两个查询时,我的WAMP崩溃的速度很慢。

很抱歉这篇长篇文章并提前致谢

2 个答案:

答案 0 :(得分:2)

问题是在INSELECT子句中使用子查询通常会导致它们再次针对外部查询中的每一行运行。要避免这种情况,请尝试加入子查询。这应该导致子查询只运行一次并缓存。

SELECT c.* 
FROM children c, (SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year) b
WHERE c.birth_year = b.birth_year

也就是说,看起来你在任何一所学校里只是每个孩子,所以更简单的JOIN也可能会给你相同的结果。

SELECT c.* 
FROM children c, school s
WHERE c.child_id = s.child_id

如果您只想获得每个学校的孩子数,那么每个出生年份

SELECT count(c.child_id), s.* 
FROM school s 
LEFT JOIN children c ON c.child_id = s.child_id
GROUP BY s.school_id, c.birth_year

答案 1 :(得分:-1)

如果您试图获得出生年份的孩子数量

SELECT COUNT (c.child_id) FROM child c INNER JOIN school s ON (c.child_id = s.child_id) GROUP BY birthyear 

如果您需要其他过滤器,那么您可以为您想要的年份添加where子句