Mysql

在子查詢中分組

  • October 18, 2018

所以我的問題如下。考慮這個查詢:

SELECT
   P.id,
   (SELECT barcode FROM product WHERE publisher_id = P.id LIMIT 1) AS barcode_sample
FROM
   publisher P
WHERE
   P.name LIKE '%tes%'

這實際上只是從產品中返回發布者 ID 和一個條碼(任何)作為範例。現在這個查詢執行得很快,並提供了我需要的東西,但我喜歡把東西放在他們的位置,所以我嘗試了以下查詢:

SELECT
   P.id,
   B.barcode AS barcode_sample
FROM
   publisher P
   LEFT JOIN
   (
       SELECT
           publisher_id,
           MAX(barcode) AS barcode
       FROM
           product
       GROUP BY
           publisher_id
   ) B
       ON P.id = B.publisher_id
WHERE
   P.name LIKE '%tes%'

幾乎相同,但使用子查詢連接和分組依據。現在,我希望 MySQL 首先從子查詢中刪除行(如 where),以便僅按加入所需的 publisher_id-s 分組。但顯然它不是那麼智能,只是讀取所有行並進行資源消耗組。

以下是按順序解釋:

+----+--------------------+---------+-------+------------------+------------------+---------+--------------+-------+--------------------------+
| id | select_type        | table   | type  | possible_keys    | key              | key_len | ref          | rows  | Extra                    |
+----+--------------------+---------+-------+------------------+------------------+---------+--------------+-------+--------------------------+
|  1 | PRIMARY            | P       | index | NULL             | name             | 452     | NULL         | 94004 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | product | ref   | idx_publisher_id | idx_publisher_id | 5       | finance.P.id |   210 | Using where              |
+----+--------------------+---------+-------+------------------+------------------+---------+--------------+-------+--------------------------+

+----+-------------+------------+-------+---------------+------------------+---------+------+----------+--------------------------+
| id | select_type | table      | type  | possible_keys | key              | key_len | ref  | rows     | Extra                    |
+----+-------------+------------+-------+---------------+------------------+---------+------+----------+--------------------------+
|  1 | PRIMARY     | P          | index | NULL          | name             | 452     | NULL |    94004 | Using where; Using index |
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL             | NULL    | NULL |    64829 |                          |
|  2 | DERIVED     | product    | index | NULL          | idx_publisher_id | 5       | NULL | 21713216 |                          |
+----+-------------+------------+-------+---------------+------------------+---------+------+----------+--------------------------+

我的問題是我能否以某種語義上更好(更好看)的方式實現我想要的,還是我必須學會忍受這個醜陋但快速的查詢?

使用 WHERE 子句更新查詢並檢查結果

您似乎正在尋找的是一個LATERAL連接,據我所知,MySQL 不支持它。就像是:

SELECT P.id, B.barcode AS barcode_sample
FROM publisher P
LEFT JOIN LATERAL (
   SELECT publisher_id, MAX(barcode) AS barcode
   FROM product x
   WHERE x.publisher_id = P.id
   GROUP BY publisher_id
) B
   ON P.id = B.publisher_id
WHERE P.name LIKE '%tes%'

如果 DBMS 支持 LATERAL,則可以使用。即使沒有 LATERAL,一些優化器也會將謂詞推送到子查詢中,但我認為 MySQL 的優化器不會。

無論如何,我不確定您為什麼需要加入子選擇,我相信以下應該有效:

SELECT P.id, MAX(B.barcode) AS barcode_sample
FROM publisher P
LEFT JOIN product B
   ON P.id = B.publisher_id
WHERE P.name LIKE '%tes%'
GROUP BY P.id 

引用自:https://dba.stackexchange.com/questions/219538