MySQL在同一个表上重复连接

时间:2012-05-23 10:22:47

标签: mysql sql join

我有一张邮政编码表:

id INT, postcode VARCHAR(8)

和那些只存储两个不同邮政编码之间的一个方向距离的邮政编码之间的距离表,所以从邮编ID 2到邮编ID 5,距离只存储为2, 5, 78.2或{{{ 1}}但不是两者。

5, 2, 78.2

距离上的主键是(from,to),我对该表中的每一列都有一个索引。

我有一个如下所示的查询:

from INT, to INT, dist DECIMAL

查询运行缓慢(正如您可能预期的那样)并将数据库锁定为副作用。

解析查询会显示postcode_distances join的此行:

SELECT *
FROM listings, postcode_distances,
     postcodes postcode_listings, postcodes postcode_searchterm
WHERE listing.`status` = 3
AND listings.category = 8
AND postcode_listings.id = listings.postcode_id
AND (
     (postcode_distances.to = postcode_listings.id AND
      postcode_distances.from = postcode_searchterm.id AND
      postcode_distances.dist < 30)
     OR
     (postcode_distances.from = postcode_listings.id AND
      postcode_distances.to = postcode_searchterm.id AND
      postcode_distances.dist < 30)
)
AND postcode_searchterm.postcode = 'AB11'
GROUP BY id_listings
ORDER BY postcode_distances.dist ASC;

在单个查询中,有什么方法可以实现两个连接(在1 | SIMPLE | postcode_distances | ALL | PRIMARY,dist,to,from | 695332 | Using where; Using join buffer from列中搜索的邮政编码是什么?

我可以使用UNION并只运行查询两次,但是在每个查询中都放了postcode_distance OR条件的每一半,但我想检查一下我是否错过了另一种更简单的方式这样做?

4 个答案:

答案 0 :(得分:1)

SELECT postcodes.id       AS SearchedId, 
       postcodes.postcode AS SearchedPostCode, 
       p1.postcode        AS FromPostCode, 
       p2.postcode        AS ToPostCode, 
       p1.id              AS FromPostCodeId, 
       p2.id              AS ToPostCodeId, 
       postcode_distances.dist 
FROM   listings 
       INNER JOIN postcodes 
         ON postcodes.id = listings.postcode_id 
       INNER JOIN postcode_distances 
         ON ( postcode_distances.to1 = postcodes.id 
               OR postcode_distances.from1 = postcodes.id ) 
       INNER JOIN postcodes p1 
         ON postcode_distances.From1 = p1.id 
       INNER JOIN postcodes p2 
         ON postcode_distances.to1 = p2.id 
WHERE  listings.status = 3 
       AND listings.category = 8 
       AND postcode_distances.dist < 30 
       AND postcodes.postcode = 'AB11' 
ORDER  BY postcode_distances.dist ASC; 

Refer Sql Fiddle sample

答案 1 :(得分:0)

如果发现错误,请尝试此评论

 select * from listings, postcode_distances pDis,postcodes post
 WHERE listing.status = 3 AND listings.category = 8
 AND (pDis.to = post.id OR pDis.from = post.id) AND post.postcode = 'AB11' 
 AND pDis.dist < 30;

答案 2 :(得分:0)

SELECT   *
FROM     listings
  JOIN   postcodes postcode_listings ON postcode_listings.id = listings.postcode_id
  JOIN   postcodes postcode_searchterm
  JOIN   postcode_distances
    ON ( (listings.postcode_id, postcode_searchterm.id)
         IN (
           (postcode_distances.to,   postcode_distances.from),
           (postcode_distances.from, postcode_distances.to)
         )
     AND postcode_distances.dist < 30
    )
WHERE    listings.status = 3
     AND listings.category = 8
     AND postcode_searchterm.postcode = 'AB11'
GROUP BY id_listings
ORDER BY postcode_distances.dist ASC;

答案 3 :(得分:0)

这是一种不同的方法:

SELECT
  MAX(CASE p.id WHEN d.`from` THEN p.postcode END) AS from_postcode,
  MAX(CASE p.id WHEN d.`to`   THEN p.postcode END) AS to_postcode,
  d.`from`,
  d.`to`,
  d.`dist`,
  MAX(l.id_listings) AS id_listings
FROM postcode_distances d
INNER JOIN postcodes p ON p.id IN (d.`from`, d.`to`)
LEFT JOIN listings l ON l.postcode_id = p.id AND l.`status` = 3 AND l.category = 8
WHERE p.postcode =  'AB11' AND l.id_listings IS     NULL
   OR p.postcode <> 'AB11' AND l.id_listings IS NOT NULL
GROUP BY
  d.`from`,
  d.`to`,
  d.`dist`
HAVING COUNT(*) = 2

查询使用外部联接到listings的特定子集,并检索在该子集中具有匹配项或具有特定postcode的行。然后对行进行分组,确保组恰好有两行。