简体   繁体   中英

MySQL query with three tables, one self referenced and with same fields. What's the best approach?

I am trying to write a query to bring together data from three tables:

---------------------------------
|   destinations                |
---------------------------------
| id    | city       | status   |
---------------------------------
| 1     | Milan      | Open     |
| 2     | Florence   | Open     |
| 3     | Venice     | Open     |
---------------------------------


---------------------------------
|   trips                       |
---------------------------------
| id    | from  | to    | train |
---------------------------------
| 1     | 1     | 2     | 2     |
| 2     | 1     | 2     | 3     |
| 3     | 2     | 1     | 2     |
| 4     | 2     | 3     | 2     |
| 5     | 1     | 3     | 1     |
| 6     | 3     | 1     | 1     |
---------------------------------


---------------------------------
|   trains                      |
---------------------------------
| id    | train                 |
---------------------------------
| 1     | T1                    |
| 2     | ChooChoo              |
| 3     | IC123                 |
---------------------------------

The idea is that I would like to be able to show my user all the trips starting or ending in - say - Florence.

Something along these lines:

-----------------------------------------------------------------
|         Query: all trains going to/from Florence              |
-----------------------------------------------------------------
| trips.id | from.id | from (city) | to.id | to. city   | train |
-----------------------------------------------------------------
| 1        | 1       | Milan       | 2     | Florence   | 2     |
| 2        | 1       | Milan       | 2     | Florence   | 3     |
| 3        | 2       | Florence    | 1     | Milan      | 2     |
| 4        | 2       | Florence    | 3     | Venice     | 2     |
-----------------------------------------------------------------

The problems that I'm facing are essentially two: the auto-referencing table of destinations (which I can easily solve with aliases) and the fact that I am trying to combine two sets of data from two different selects (which I thought of solving with temporary tables).

Now, it's all good if it wasn't that some columns have the same names. Because I want to preserve the "ids" in my temporary table (to be used with links) I can't create a temporary table with a wildcard (eg. SELECT * FROM), but I would have to spell out all the columns and write a monstrous query. It will work, but it won't be flexible, and if I'll add other columns in the future, it will be hell updating it!

Can any MySQL guru maybe suggest a better approach please?

Thanks and cheers from Australia.

when you build a report, usually isn't a good idea to use SELECT *, because when i modify a table, the report can shows wrong result.

usually i prefere to write the id field with id_content, ex. id_destination, id_to, id_train, ecc...

SELECT trips.id, f.id, f.city, t.id, t. city, trains.train 
FROM trips trips
INNER JOIN destinations f
ON trips.from = f.id
INNER JOIN destinations t
ON trips.from = t.id
INNER JOIN trains trains
ON trips.train = trains.id
ORDER BY 1 ASC

G'day...

DROP TABLE IF EXISTS destinations;

CREATE TABLE destinations
(city_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,city    VARCHAR(12) NOT NULL UNIQUE
,status  VARCHAR(12) NOT NULL
);

INSERT INTO destinations VALUES
(1,'Milan','Open'),
(2,'Florence','Open'),
(3,'Venice','Open');

DROP TABLE IF EXISTS trips;

CREATE TABLE trips
(trip_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY 
,from_city_id INT NOT NULL
,to_city_id INT NOT NULL
,train INT NOT NULL
,UNIQUE(from_city_id,to_city_id,train)
);

INSERT INTO trips VALUES
(1,1,2,2),
(2,1,2,3),
(3,2,1,2),
(4,2,3,2),
(5,1,3,1),
(6,3,1,1);

DROP TABLE IF EXISTS trains;

CREATE TABLE trains
(train_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,train VARCHAR(12) NOT NULL UNIQUE
);

INSERT INTO trains VALUES
(1,'T1'),
(2,'ChooChoo'),
(3,'IC123');

SELECT * FROM destinations;
+---------+----------+--------+
| city_id | city     | status |
+---------+----------+--------+
|       1 | Milan    | Open   |
|       2 | Florence | Open   |
|       3 | Venice   | Open   |
+---------+----------+--------+

SELECT * FROM trips;
+---------+--------------+------------+-------+
| trip_id | from_city_id | to_city_id | train |
+---------+--------------+------------+-------+
|       1 |            1 |          2 |     2 |
|       2 |            1 |          2 |     3 |
|       5 |            1 |          3 |     1 |
|       3 |            2 |          1 |     2 |
|       4 |            2 |          3 |     2 |
|       6 |            3 |          1 |     1 |
+---------+--------------+------------+-------+

SELECT * FROM trains;
+----------+----------+
| train_id | train    |
+----------+----------+
|        2 | ChooChoo |
|        3 | IC123    |
|        1 | T1       |
+----------+----------+

SELECT t.trip_id
     , t.from_city_id
     , from_city.city
     , t.to_city_id
     , to_city.city
     , t.train 
  FROM trips t 
  JOIN destinations from_city 
    ON from_city.city_id = t.from_city_id 
  JOIN destinations to_city 
    ON to_city.city_id = t.to_city_id 
 WHERE 'Florence' IN(from_city.city,to_city.city);
+---------+--------------+----------+------------+----------+-------+
| trip_id | from_city_id | city     | to_city_id | city     | train |
+---------+--------------+----------+------------+----------+-------+
|       3 |            2 | Florence |          1 | Milan    |     2 |
|       4 |            2 | Florence |          3 | Venice   |     2 |
|       1 |            1 | Milan    |          2 | Florence |     2 |
|       2 |            1 | Milan    |          2 | Florence |     3 |
+---------+--------------+----------+------------+----------+-------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM