优化小型MySQL加入查询

时间:2011-09-08 14:51:18

标签: php mysql join query-optimization

我在Venues表中有一个场地列表,以及Locations表中的城市/州列表。场地与我的组织特有的区号相关联,称为SOYID。 SOYID由地理区域组成 - 位置表中的每一行都有一个城市,州和相应的SOYID。 有些场地的行有SOYID,有些则没有;对于那些没有的人,我需要找到所列城市和州的SOYID。我只想在特定的SOYID中选择那些场地。

此查询有效,但加载需要几秒钟;我不认为我正在编写查询。目前场馆大约有140排,地点有40,000个。

    $sql = "SELECT DISTINCT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
            FROM Venues AS a LEFT JOIN Locations AS c ON a.City = c.city
            WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
            OR ((c.city = a.City) AND  (c.state = a.StateAbbr) AND (c.SOYID = '" . mysql_real_escape_string($SOYID) . "'))
            ORDER BY a.Name ASC";

1 个答案:

答案 0 :(得分:2)

每次在WHERE子句中引用LEFT JOINed表(在特定情况下为c.statec.SOYID)中的列时,都会强制该连接的行为类似于INNER JOIN。相反,将这些测试作为连接条件的一部分:

"SELECT DISTINCT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
    FROM Venues AS a 
        LEFT JOIN Locations AS c 
            ON a.City = c.city
                AND a.StateAbbr = c.state
                AND c.SOYID = '" . mysql_real_escape_string($SOYID) . "'
    WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
        OR c.SOYID IS NOT NULL /* LEFT JOIN found a matching row */
    ORDER BY a.Name ASC"

编辑:根据评论,此版本应该允许您删除DISTINCT要求:

"SELECT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
    FROM Venues AS a 
    WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
        OR EXISTS(SELECT NULL
                      FROM Locations AS c 
                      WHERE a.City = c.city
                          AND a.StateAbbr = c.state
                          AND c.SOYID = '" . mysql_real_escape_string($SOYID) . "') 
    ORDER BY a.Name ASC"