Еще один способ улучшить SQL-запрос, чтобы избежать объединения? - PullRequest
8 голосов
/ 10 февраля 2012

Пользователь может выполнять поиск по почтовому индексу (например, L14, L15, L16) или по местоположению из текстового поля.

Если пользователь введет «Ливерпуль», он найдет все магазины, расположенные в «Ливерпуле». Если пользователь вводит почтовый индекс (например, 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          |
+----+----------+-----------+----------+---------------+--------------+

Кажется, он работает правильно ... Есть ли другой способ улучшить SQL-запрос короче, чтобы избежать union или что-то еще?

Ответы [ 4 ]

1 голос
/ 10 февраля 2012

Что бы вы ни выбрали, помните, что короткий код не всегда является оптимальным кодом.Во многих случаях, когда у вас достаточно расходящаяся логика, объединение результатов действительно является наиболее оптимальным (а иногда и наиболее чистым, программным) вариантом.чехлы ...

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")
1 голос
/ 10 февраля 2012

Поскольку все таблицы и выбранные столбцы одинаковы, вы можете просто сделать это:

  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")

Как вы сказали в ответе Диего, условия немного разные!Таким образом, вы компенсируете эту разницу в WHERE clause.

0 голосов
/ 10 февраля 2012

пожалуйста, попробуйте это:

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)
0 голосов
/ 10 февраля 2012

Чего мне не хватает? Почему ты не можешь

 WHERE DA.postcode = "Liverpool" or shops.location = "Liverpool"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...