2012-02-10 12 views
7

ユーザーは、郵便番号(例:L14、L15、L16)または場所をテキストボックスから検索することができます。結合を回避するためにSQLクエリを改善する別の方法はありますか?

「Liverpool」にユーザーが入力すると、「Liverpool」にあるすべてのお店が検索されます。ユーザーが郵便番号(例:L15)に入力すると、L15の郵便番号帯で配達を行うすべての店舗が検索されます。

mysql> select * from shops; 
+----+----------+-----------+----------+ 
| id | name  | location | postcode | 
+----+----------+-----------+----------+ 
| 1 | Shop One | Liverpool | L10  | 
| 2 | Shop Two | Liverpool | L16  | 
+----+----------+-----------+----------+ 

-

mysql> select * from shops_delivery_area; 
+------------------+---------+----------+---------------+ 
| delivery_area_id | shop_id | postcode | delivery_cost | 
+------------------+---------+----------+---------------+ 
|    1 |  1 | L10  |   1.50 | 
|    2 |  1 | L11  |   0.00 | 
|    3 |  1 | L12  |   1.00 | 
|    4 |  1 | L13  |   1.00 | 
|    5 |  2 | L10  |   2.50 | 
|    6 |  2 | L16  |   0.00 | 
|    7 |  2 | L28  |   0.00 | 
+------------------+---------+----------+---------------+ 

SQLクエリ:

は以下の表を参照してください

SELECT U.* FROM 
    ((SELECT DISTINCT shops.*, DA.delivery_cost, DA.postcode AS AreaPostcode FROM shops 
      JOIN shops_delivery_area as DA on (DA.shop_id = shops.id) 
    WHERE DA.postcode = "Liverpool") 
    UNION 
    (SELECT DISTINCT shops.*, DA.delivery_cost, DA.postcode AS AreaPostcode FROM shops 
      JOIN shops_delivery_area as DA on 
           (DA.shop_id = shops.id AND 
           DA.postcode = shops.postcode) 
    WHERE shops.location = "Liverpool")) as U 

-

結果 - 場所(リバプール)によって:

+----+----------+-----------+----------+---------------+--------------+ 
| id | name  | location | postcode | delivery_cost | AreaPostcode | 
+----+----------+-----------+----------+---------------+--------------+ 
| 1 | Shop One | Liverpool | L10  |   1.50 | L10   | 
| 2 | Shop Two | Liverpool | L16  |   0.00 | L16   | 
+----+----------+-----------+----------+---------------+--------------+ 

結果 - 郵便番号(L12)によって:

+----+----------+-----------+----------+---------------+--------------+ 
| id | name  | location | postcode | delivery_cost | AreaPostcode | 
+----+----------+-----------+----------+---------------+--------------+ 
| 1 | Shop One | Liverpool | L10  |   1.00 | L12   | 
+----+----------+-----------+----------+---------------+--------------+ 

それが正しく動作するように見える... は改善する他の方法はありますunionまたは何かを避けるために短いSQLクエリ?

+0

...句は、あなたのケースの両方をカバーするようだWHEREで、次のOR、言っ

? p.s. UNION DISTINCTの略号であるため、DISTINCTキーワードを削除することができます。 – onedaywhen

答えて

1

は、短いコードは、常に最適なコードではないことに注意してください。多くの場合、十分に分岐したロジックを持つ場所では、実際に最適化された(場合によっては最もきれいな、プログラマチックに)オプションが結果を統合します。あなたは `UNION`を避けるためにどのような根拠を持っているん

SELECT DISTINCT 
    shops.*, 
    DA.delivery_cost, 
    DA.postcode AS AreaPostcode 
FROM 
    shops 
INNER JOIN 
    shops_delivery_area as DA 
    ON (DA.shop_id = shops.id) 
WHERE 
    (DA.postcode = "Liverpool") 
OR 
    (DA.postcode = shops.postcode AND shops.location = "Liverpool") 
+0

ありがとう!だからパフォーマンスの賢明なオプションが良いだろうか?連合またはWHERE句での「OR」とのスティック –

+0

私はパフォーマンステストを行ったばかりです。「Union」を使用している方が高速です。 –

+0

@ user791022 sayd '私はパフォーマンステストを行ったばかりです。連合はより速く表示されます。** **私はあなたに言った**テーブルの真ん中またはテーブル全体の2つのインデックスヒットが速いのは何ですか? ? SQLに「アプリケーション」の考え方(冗長コードの削減など)を適用すると、パフォーマンスの問題が発生します。 –

0

何が欠けていますか? は、なぜあなたはすべてのテーブルと、選択した列が同じであるので、あなたは、単にこれを行うことができます

WHERE DA.postcode = "Liverpool" or shops.location = "Liverpool" 
+0

それは正しく動作しません、そうでなければ、同じ店名の多くの行を取得します。 'JOIN'を注意深く見てください。 –

+1

を使用すると、索引の使用方法に応じてパフォーマンスが低下する可能性があります。私は通常、 'OR'を回避し、' UNION'の各部分でインデックスを使用することで実質的なパフォーマンスを得るために、このようなクエリを 'UNION'に分割します。 –

+0

@Diego、 'stores.location =" Liverpool "'の場合、1つの制限がありません。 –

1

んカント:あなたはサンディエゴの答えに言ったように

SELECT DISTINCT shops.*, DA.delivery_cost, DA.postcode AS AreaPostcode FROM shops 
      JOIN shops_delivery_area as DA on DA.shop_id = shops.id 
    WHERE (DA.postcode = "Liverpool") 
     OR (DA.postcode = shops.postcode AND shops.location = "Liverpool") 

を、条件がlitle異なっています!したがって、WHERE clauseの違いを補うことができます。

0

これを試してください:あなたが選ぶどのような

SELECT DISTINCT shops.*, 
     DA.delivery_cost, 
     DA.postcode 
FROM shops 
     JOIN shops_delivery_area as DA on DA.shop_id = shops.id 
WHERE DA.postcode = "Liverpool" 
     OR (location = "Liverpool" and DA.postcode = shops.postcode) 
関連する問題