0

郵便番号の表があります。

id INT, postcode VARCHAR(8)

また、2つの異なる郵便番号間の1方向の距離のみを格納する、これらの郵便番号間の距離のテーブル。したがって、郵便番号ID2から郵便番号ID5までの距離は、as2, 5, 78.2またはasのいずれかでのみ保存され5, 2, 78.2、両方では保存されません。

from INT, to INT, dist DECIMAL

距離の主キーは(from、to)であり、そのテーブルの各列にもインデックスがあります。

次のようなクエリがあります。

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;

クエリの実行は遅く(おそらく予想どおり)、副作用としてデータベースがロックされます。

クエリを説明すると、postcode_distances結合の次の行が表示されます。

1 | SIMPLE | postcode_distances | ALL | PRIMARY,dist,to,from | 695332 | Using where; Using join buffer

1つのクエリで2つの結合(検索される郵便番号がfromまたはto列のいずれかである場合)を実現する方法はありますか?

UNIONを使用して、クエリを2回実行することもできますが、postcode_distance OR条件の各半分を各クエリに入れますが、これを行う別のより簡単な方法を見逃していないかどうかを確認したかったのでしょうか。

4

4 に答える 4

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; 

Sql Fiddle のサンプルを参照

于 2012-05-23T10:41:45.503 に答える
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;
于 2012-05-23T12:02:53.373 に答える
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;
于 2012-05-23T11:59:45.607 に答える
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。次に、行がグループ化され、グループが正確に 2 行になるようにします。

于 2012-05-23T14:08:11.580 に答える