调整SQL查询。如何将IN更改为更快的内容

时间:2012-01-28 08:56:15

标签: php mysql sql

我有一个网站在输入搜索词时向Mysql运行查询。我像这样构建了一个sql语句

SELECT * FROM catelogue
WHERE `DEPARTMENT` LIKE 'MUSIC'
AND ( `ARTIST` LIKE '%$theValue%' OR `TITLE` LIKE '%$theValue%' OR 
    `CAT NO.` IN 
    (SELECT `TRACKLISTING CAT NO.`
    FROM tracklisting 
    WHERE `ARTIST` LIKE '%$theValue%' OR `TRACK TITLE` LIKE '%$theValue%'))
    ORDER BY `RELEASEDATE` DESC

在测试时,它在本地的wamp上工作得很好。现在我已将网站上传到我的主机,查询似乎崩溃或减慢了它甚至没有加载页面。

我将查询重新设计为此

SELECT `ARTIST` , `TITLE` , `CAT NO.` , `FORMAT` , `DEPARTMENT` , `SELL`,`IMAGE PATH` 
        FROM catelogue
WHERE `DEPARTMENT` LIKE 'MUSIC'
AND ( `ARTIST` LIKE '%$theValue%' OR `TITLE` LIKE '%$theValue%') 
    ORDER BY `RELEASEDATE` DESC"

由于这一点,它现在在我的主机上运行良好,但我无法搜索我的跟踪列表。我需要知道如何将IN更改为更快的效果。

catelogue和跟踪列表由CAT NO。

链接

由于

修改

非常感谢所有帮助过的人

现在有些坏消息。这是我现在使用的代码。它不会返回任何错误,但它也不会返回任何结果

SELECT c.`ARTIST` , c.`TITLE` , c.`CAT NO.` , c.`FORMAT` , c.`DEPARTMENT` , c.`SELL` 
FROM    catelogue c
LEFT JOIN   tracklisting t
        ON  t.`TRACKLISTING CAT NO.` = c.`CAT NO.`
WHERE   'DEPARTMENT' = 'MUSIC'
        AND ((  c.`ARTIST` LIKE '%$theValue%' OR c.`TITLE` LIKE '%$theValue%')
                OR
                (t.`ARTIST` LIKE '%$theValue%' OR t.`TRACK TITLE` LIKE '%$theValue%'))

跟踪表没有catelogue表中每个条目的所有跟踪列表。这会有所作为吗?

我知道在ms访问中你可以设置与表的关系,但是我一直无法弄清楚这是否可以在phpmyadmin中完成,我是否必须在表之间建立关系才能使其工作?

非常感谢

3 个答案:

答案 0 :(得分:2)

好吧,我真的不做PHP,所以你的一些语法对我来说有些陌生,但是sql是sql而且我只是复制了我不熟悉的位。

这应该做你想要的:

SELECT  *
FROM    catelogue c
    LEFT JOIN   tracklisting t
        ON  t.`TRACKLISTING CAT NO.` = c.`CAT NO.`
WHERE   `DEPARTMENT` = 'MUSIC'
        AND ((  c.'ARTIST' LIKE '%$theValue%' OR c.'TITLE' LIKE '%$theValue%')
                OR
                (t.`ARTIST` LIKE '%$theValue%' OR t.`TRACK TITLE` LIKE '%$theValue%'))
ORDER BY    `RELEASEDATE` DESC

顺便说一句,这个数据库中的字段命名只是可怕的恕我直言。如果您可以执行某种形式的全文索引,这也可能会有所帮助,以便这些“包含”LIKE比较不会导致您每次都执行全表扫描。只是一个想法。

答案 1 :(得分:1)

您可以使用连接两个表而不是使用in子句:

SELECT 
    C.`ARTIST` , 
    C.`TITLE` , 
    C.`CAT NO.` , 
    C.`FORMAT` , 
    C.`DEPARTMENT` , 
    C.`SELL`, 
    C.`IMAGE PATH` 
FROM catelogue C LEFT JOIN tracklisting T
    ON C.`CAT NO.` = T.`TRACKLISTING CAT NO.`
WHERE 
    C.`DEPARTMENT` = 'MUSIC'
    AND (C.`ARTIST` LIKE C.'%$theValue%' OR C.`TITLE` LIKE '%$theValue%') 
    AND (T.`ARTIST` LIKE T.'%$theValue%' OR T.`TRACK TITLE` LIKE '%$theValue%')
ORDER BY 
    `RELEASEDATE` DESC

请注意,我将第一个条件从LIKE更改为=(更快),并认为性能受索引可用性和查询结构的影响;例如,你可以:

  • 评估你是否可以在没有第一个%
  • 的情况下做喜欢
  • 如果是这样,您可以在C。ARTIST和C。TITLE上添加一个索引,在T上添加一个索引。ARTIST和T. TRACK TITLE
  • 在C。DEPARTMENT
  • 上添加索引

答案 2 :(得分:0)

我没有测试过这个查询,但我认为这是一个好的开始。使用LEFT join insted of your structure:

SELECT * FROM catelogue  c
LEFT JOIN  tracklisting  t
ON c.`CAT NO.` = t.`TRACKLISTING CAT NO.`
WHERE c.`DEPARTMENT` LIKE 'MUSIC'
AND ( c.`ARTIST` LIKE '%$theValue%' OR c.`TITLE` LIKE '%$theValue%')
OR (t.`ARTIST` LIKE '%$theValue%' OR t.`TRACK TITLE` LIKE '%$theValue%')
ORDER BY c.`RELEASEDATE` DESC