Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 在WHERE或FROM子句中进行子选择?_Mysql_Sql_Query Optimization - Fatal编程技术网

Mysql 在WHERE或FROM子句中进行子选择?

Mysql 在WHERE或FROM子句中进行子选择?,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,我想知道如果特定的subselect(subquery)位于WHERE或FROM子句中,查询的一般性能如何。我没有找到足够的解释哪种方式更好。在这种查询中,我们应该如何应用subselect有一些规则吗 我准备了下面的例子 来自的查询 SELECT name FROM users a JOIN (SELECT user_id, AVG(score) as score FROM scores GROUP BY user_id ) b O

我想知道如果特定的subselect(subquery)位于
WHERE
FROM
子句中,查询的一般性能如何。我没有找到足够的解释哪种方式更好。在这种查询中,我们应该如何应用subselect有一些规则吗

我准备了下面的例子

来自的查询

SELECT name 
FROM users a 
  JOIN (SELECT user_id, AVG(score) as score
               FROM scores GROUP BY user_id
            ) b ON a.id=b.user_id 
  WHERE b.score > 15;
在何处查询

SELECT name 
FROM users 
WHERE 
  (SELECT AVG(score) as score
     FROM scores WHERE scores.user_id=users.id GROUP BY user_id
  ) > 15;
表:

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(30));
  
CREATE TABLE scores (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  score INT);
  
INSERT INTO users(name)
  VALUES ('John'), ('Max'), ('Dan'), ('Alex');
  
INSERT INTO scores(user_id, score)
  VALUES
  (1, 20),
  (1, 19),
  (2, 15),
  (2, 10),
  (3, 20),
  (3, 18),
  (4, 13),
  (4, 16),
  (4, 15);

在这两种情况下,
分数
需要
索引(用户id,分数)
来提高性能

很难预测哪个会跑得更快

有时,类似于第一个公式的查询非常出色。这是因为它会离开一个专注于
b
的窗口,并一次有效地计算所有平均值。然后它到达另一个表以获取最终信息

让我们稍微调整一下第二个版本,在
WHERE
子句中添加一些其他测试。现在第二个可能更快

这可能更好:

SELECT name 
    FROM ( SELECT user_id      -- Don't fetch AVG if not needed
               FROM scores GROUP BY user_id
               HAVING  AVG(score) > 15;      -- Note
         ) b
    JOIN users a  ON a.id = b.user_id 
(FROM和JOIN的交换不是优化;它只是显示优化器执行步骤的顺序。)

在其他一些情况下,
存在(选择…
是有益的。(但在你的情况下,我看不到这种情况


你的问题是关于一般优化的。我想强调的是没有一般的答案。

我认为这个请求比你上面给出的更快,因为它没有子查询

SELECT u.name
FROM users u
JOIN scores s 
  ON (s.user_id = u.id)
GROUP BY s.user_id
HAVING AVG(s.score) > 15
您可以在此链接上看到: 它显示了接下来3个Select查询的执行时间:

SELECT name 
FROM users a 
  JOIN (SELECT user_id, AVG(score) as score
               FROM scores GROUP BY user_id
            ) b ON a.id=b.user_id 
  WHERE b.score > 15;
  
SELECT name 
FROM users 
WHERE 
  (SELECT AVG(score) as score
     FROM scores WHERE scores.user_id=users.id GROUP BY user_id
  ) > 15;

SELECT u.name
FROM users u
JOIN scores s 
  ON (s.user_id = u.id)
GROUP BY s.user_id
HAVING AVG(s.score) > 15 

您使用的是哪种dbms?您比较过解释/执行计划吗?通常是mysql,但它是否依赖于dbms?尝试运行这两个查询,并选择一个对您的系统和数据最有效的查询。因为
其中b.score…
LEFT
不相关。请删除它。我认为在第二个查询中,我们每个人都会计算AVG呃,分开来说,它应该会慢一些。但是后来我看到一些数据库管理系统优化了这种查询,一次计算了所有的查询,我想知道这个技巧的优势在哪里。谢谢。我认为这是一个简单的问题。只需知道MySQL是如何工作的。@Tajni-一些简单的问题有简单的答案,一些没有。s由于MySQL不断发展,一些答案会随着时间的推移而改变。MySQL 4.0(20年前)中不存在子查询。5.6在这方面添加了一些显著的性能增强。等等。