Reputation: 92
I have two tables. The first one holds information about cities:
Locations:
locID | locationID | locationName | countryCode |
1 | 2922239 | Berlin | de |
2 | 291074 | Paris | fr |
3 | 295522 | Orlando | us |
3 | 292345 | Tokyo | jp |
There is a second table, which holds alternative names for locations. There might be NO alternative name for a location in the Locations table: AlternateNames:
altNameID | locationID | alternateName |
1 | 2922239 | Berlino |
2 | 2922239 | Berlina |
3 | 2922239 | capital |
4 | 291074 | Parisa |
5 | 291074 | Pariso |
6 | 295522 | Orlandola |
7 | 295522 | Orlandolo |
What I would like to get is the locationID, name and the countryCode of a location for a location name search like "Berlin", or "Ber":
| locationID | name | countryCode |
| 2922239 | Berlin | de |
However, if the user searches for "Berlino", I would like to get the alternateName back:
| locationID | name | countryCode |
| 2922239 | Berlino | de |
The "locationName" has a higher priority than the alternateName, if the searchterm matches both.
I can't figure out how to build a query to do that. Since the name can come from one of the two tables, it seems quite difficult to me.
Any help is really appreciated!
Upvotes: 1
Views: 1584
Reputation: 4152
SELECT
locationID,
(IF (name LIKE 'Ber%', name, alternateName)) as name,
countryCode
FROM
Locations l LEFT JOIN AlternateNames a ON (l.locationID = a.locationID)
WHERE
name LIKE 'Ber%'
OR
alternateName LIKE 'Ber%'
Obviously, use variable substitution (:searchname) in place of 'Ber%'.
Add LIMIT 1
to the end of the query if you only want 1 row returned.
Edited based on comment about preference for alternateName. Made LEFT join per Schultz999 suggestion
Upvotes: 3
Reputation: 1760
This query joins the two tables via a union query, ranks them and takes the top result from the union.
Try this:
SELECT
locationID
, `name`
, countryCode
FROM
(
SELECT
locationID
, `name`
, countryCode
, 1 AS priority
FROM
locations
WHERE
locationName LIKE 'Ber%'
UNION
SELECT
a.locationID
, a.alternateName AS `name`
, l.countryCode
, 2 as priority
FROM
AlternateNames a
INNER JOIN Locations l
ON a.locationID = l.locationID
WHERE
a.alternateName LIKE 'Ber%'
) u
ORDER BY
priority
LIMIT 1
Upvotes: 0
Reputation: 82893
Try this:
SELECT a.locationID, :locationName, a.countryCode // :locationName being the city name parameter
FROM cities a, locations b
WHERE a.locationID = b.locationID
AND (a.locationName = :locationName OR b.alternateName = :locationName )
SELECT a.locationID, a.locationName, a.countryCode
FROM cities a
WHERE a.locationName = :locationName
UNION ALL
SELECT a.locationID, b.alternateName locationName, a.countryCode
FROM cities a, locations b
WHERE a.locationID = b.locationID
AND b.alternateName = :locationName
Upvotes: 0
Reputation: 2409
something like this should do this.
select a.locationID, coalesce(b.alternateName,a.locationName), a.countrycode FROM table1 a LEFT JOIN table2 b ON a.locationId=B.locationID where a.locationName=?
Upvotes: 0