簡體   English   中英

在 WHERE 或 FROM 子句中進行子選擇?

[英]Subselect in WHERE or FROM clause?

如果特定的子選擇(子查詢)位於WHEREFROM子句中,我想知道查詢的一般性能。 我沒有找到足夠的解釋哪種方式更好。 我們應該如何在此類查詢中應用 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;

查詢 WHERE

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);

在這兩種情況下, scores需要INDEX(user_id, score)以提高性能。

很難預測哪個會跑得更快。

有時,類似於第一個公式的查詢非常好。 這是因為它關閉了對b的關注,並且一次有效地計算了所有的 AVG。 然后它到達另一個表以獲取最終信息。

讓我們通過在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 的交換不是優化;它只是為了顯示優化器將執行這些步驟的順序。)

在其他一些情況下, EXISTS( SELECT ... )是有益的。 (但我在你的情況下沒有看到這種情況。

你的問題是關於一般優化。 我想強調的是,沒有普遍的答案。

我認為這個請求比你上面給出的要快,因為它沒有子查詢。

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

您可以在此鏈接上看到它: http : //sqlfiddle.com/#!9/b050f9/16它顯示了接下來 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 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM