【问题标题】:MySQL query with three tables, one self referenced and with same fields. What's the best approach?MySQL 查询具有三个表,一个自引用且具有相同的字段。最好的方法是什么?
【发布时间】:2015-08-21 08:44:21
【问题描述】:

我正在尝试编写一个查询来汇总三个表中的数据:

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

我的想法是,我希望能够向我的用户展示从佛罗伦萨开始或结束的所有旅行。

类似的东西:

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

我面临的问题基本上有两个:目标的自动引用表(我可以使用别名轻松解决)以及我试图组合来自两个不同选择的两组数据的事实(我考虑用临时表解决)。

现在,如果不是某些列具有相同的名称,那就太好了。因为我想在我的临时表中保留“ids”(与链接一起使用)我不能用通配符创建一个临时表(例如 SELECT * FROM),但我必须拼出所有列和写一个可怕的查询。它会工作,但它不会灵活,如果我将来添加其他列,更新它会很糟糕!

请任何 MySQL 专家提出更好的方法吗?

来自澳大利亚的感谢和欢呼。

【问题讨论】:

  • 抱歉,但我不明白“在 (a.from=b.id) .... 上旅行左连接目的地 b”有什么问题。
  • (虽然我知道您在 SO 上找到了 100 个示例,但我没有这样做...)您应该始终在 SELECT 中命名列。如果做不到,通常说明设计存在缺陷。
  • 好点@Strawberry 也许我应该审查设计,虽然这个例子(和你的解决方案)的简单性让我觉得这已经不是太糟糕了。再次感谢。

标签: mysql temp-tables


【解决方案1】:

生日...

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 |
+---------+--------------+----------+------------+----------+-------+

【讨论】:

  • 谢谢你,我没想过用多个连接 + OR 使用 IN() 重写查询。简单而精彩。
【解决方案2】:

当您构建报表时,使用 SELECT * 通常不是一个好主意, 因为当我修改表格时,报告可能会显示错误的结果。

通常我更喜欢用 id_content 编写 id 字段,例如。 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

【讨论】:

  • 感谢 Stamprsist。我也很喜欢这个主意(看起来我会走这条路)。
猜你喜欢
  • 1970-01-01
  • 2015-01-29
  • 1970-01-01
  • 2013-12-23
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
相关资源
最近更新 更多