【问题标题】:MySQL - Find rows matching all rows from joined table AND string from other tablesMySQL - 查找与连接表中的所有行和其他表中的字符串匹配的行
【发布时间】:2010-11-17 17:33:28
【问题描述】:

这是MySQL - Find rows matching all rows from joined table的后续跟进

感谢这个网站,查询运行完美。

但现在我不得不扩展查询以搜索艺术家和曲目。这导致我进行以下查询:

SELECT DISTINCT`t`.`id` 
FROM `trackwords` AS `tw`  
INNER JOIN `wordlist` AS `wl` ON wl.id=tw.wordid  
INNER JOIN `track` AS `t` ON tw.trackid=t.id  
WHERE (wl.trackusecount>0) AND  
(wl.word IN ('please','dont','leave','me')) AND  
t.artist IN ( 
 SELECT a.id  
 FROM artist as a 
 INNER JOIN `artistalias` AS `aa` ON aa.ref=a.id  
 WHERE a.name LIKE 'pink%' OR  aa.name LIKE 'pink%' 
)  
GROUP BY tw.trackid 
HAVING (COUNT(*) = 4);

我认为这个查询的解释看起来相当不错:

+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+
| id | select_type        | table | type   | possible_keys              | key     | key_len | ref             | rows | Extra                                        |
+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+
|  1 | PRIMARY            | wl    | range  | PRIMARY,word,trackusecount | word    | 767     | NULL            |    4 | Using where; Using temporary; Using filesort | 
|  1 | PRIMARY            | tw    | ref    | wordid,trackid             | wordid  | 4       | mbdb.wl.id      |   31 |                                              | 
|  1 | PRIMARY            | t     | eq_ref | PRIMARY                    | PRIMARY | 4       | mbdb.tw.trackid |    1 | Using where                                  | 
|  2 | DEPENDENT SUBQUERY | aa    | ref    | ref,name                   | ref     | 4       | func            |    2 |                                              | 
|  2 | DEPENDENT SUBQUERY | a     | eq_ref | PRIMARY,name,namefull      | PRIMARY | 4       | func            |    1 | Using where                                  | 
+----+--------------------+-------+--------+----------------------------+---------+---------+-----------------+------+----------------------------------------------+

您看到优化空间了吗? Query 的运行时间大约为 7 秒,不幸的是。欢迎提出任何建议。

TIA

【问题讨论】:

    标签: mysql join query-optimization


    【解决方案1】:

    这里有两个可能的选择条件:artists's nameword list

    假设这些词比艺术家更有选择性:

    SELECT  tw.trackid 
    FROM    (
            SELECT  tw.trackid
            FROM    wordlist AS wl
            JOIN    trackwords AS tw  
            ON      tw.wordid = wl.id
            WHERE   wl.trackusecount > 0
                    AND wl.word IN ('please','dont','leave','me')
            GROUP BY
                    tw.trackid
            HAVING  COUNT(*) = 4
            ) tw
    INNER JOIN
            track AS t
    ON      t.id = tw.trackid
            AND EXISTS
            (
            SELECT  NULL
            FROM    artist a
            WHERE   a.name LIKE 'pink%'
                    AND a.id = t.artist
            UNION ALL
            SELECT  NULL
            FROM    artist a
            JOIN    artistalias aa
            ON      aa.ref = a.id
                    AND aa.name LIKE 'pink%'
            WHERE   a.id = t.artist
            )                
    

    您需要有以下索引才能有效:

    wordlist (word, trackusecount)
    trackwords (wordid, trackid)
    artistalias (ref, name)
    

    【讨论】:

    • 哇,太好了。我想我理解你在做什么,但是 mysql 给出:#1248 - 据我所知,每个派生表都必须有自己的别名,它应该是给出错误的轨道 (t),但我不能弄清楚如何解决这个问题。
    • @Rufinus:如果您将表定义连同查询一起发布,这样人们就可以在发布前检查语法。
    • @Quassnoi:谢谢谢谢谢谢。它比我的版本快 700%,太棒了!下次我将链接一个 sql 结构文件。 (不想用 5 个表结构来解决这个问题 :-) 再次感谢
    • @Rufinus: 不客气 :) “提出问题”完全没问题:摆脱结构非常容易,但如果你不知道就很难弥补它。
    【解决方案2】:

    您是否已经为名称列编制了索引?这应该会加快速度。

    您也可以尝试通过 Match 和 Against 使用全文搜索。

    【讨论】:

      猜你喜欢
      • 2014-11-05
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 2012-06-13
      • 1970-01-01
      相关资源
      最近更新 更多