Reputation: 10828
User can search by Postcode (eg: L14, L15, L16) or Location from a textbox.
If user type in "Liverpool", it will find all the shops that are located in "Liverpool". If User type in the postcode (Eg: L15), it will search all the shops that do delivery in L15 postcode zone.
See the Tables below:
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 Query:
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
-
Result - by Location (Liverpool):
+----+----------+-----------+----------+---------------+--------------+
| id | name | location | postcode | delivery_cost | AreaPostcode |
+----+----------+-----------+----------+---------------+--------------+
| 1 | Shop One | Liverpool | L10 | 1.50 | L10 |
| 2 | Shop Two | Liverpool | L16 | 0.00 | L16 |
+----+----------+-----------+----------+---------------+--------------+
Result - by Postcode (L12):
+----+----------+-----------+----------+---------------+--------------+
| id | name | location | postcode | delivery_cost | AreaPostcode |
+----+----------+-----------+----------+---------------+--------------+
| 1 | Shop One | Liverpool | L10 | 1.00 | L12 |
+----+----------+-----------+----------+---------------+--------------+
It appear to be working correctly...
Is there other way to improve the SQL query shorter to avoid union
or something?
Upvotes: 9
Views: 10805
Reputation: 86715
Whatever you choose, be aware that short code is not always optimal code. In many cases, where you have sufficiently divergent logic, unioning the results really is the most optimal (and sometimes most clean, programatically) option.
That said, the following OR in the WHERE clause seems to cover both your cases...
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")
Upvotes: 2
Reputation: 66697
Since all tables and selected columns are the same, you can simply do this:
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")
Like you said in Diego's answer, the conditions are a litle different! So, you compensate that difference in the WHERE clause
.
Upvotes: 1
Reputation: 8333
please try this:
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)
Upvotes: 1
Reputation: 36146
What am I missing? Why cant you do
WHERE DA.postcode = "Liverpool" or shops.location = "Liverpool"
Upvotes: 0