Mysql
在子查詢中分組
所以我的問題如下。考慮這個查詢:
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