SQL 和外键的逻辑问题

Logical Trouble with SQL and foreign key

已编辑*1

我是软件开发人员的实习生,所以我对 MySQL-数据库没有太多经验。

我想为任务写一个工单,它包含了工人的详细信息以及需要哪个工人。

我在数据库中有一个 table,其中包含工人的姓名和部门。

table worker 看起来像这样:

+---------+---------+----------+------------+
| id (PK) | surname | forename | department |
+---------+---------+----------+------------+
| 1       | bar     | foo      | shop       |
+---------+---------+----------+------------+
| 2       | baz     | foo      | production |
...

而 table tasks 看起来像这样:

+---------+------------+----------+-------------+----------------+-------------------+----
| id (PK) | task       | shop_req | shop_worker | production_req | production_worker | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 1       | do sth.    | yes      | 1           | yes            | 2                 | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 2       | do sth.    | no       | (NULL)      | yes            | 2                 | ...
...

如何将它们连接在一起?

我试过这个SQL-代码:*1

ALTER TABLE tasks

ADD CONSTRAINTS FK_tasks_shop
FOREIGN KEY (shop_worker) 
REFERENCES worker(id) 
ON UPDATE RESTRICT
ON DELETE RESTRICT,

ADD CONSTRAINTS FK_tasks_production
FOREIGN KEY (production_worker) 
REFERENCES worker(id) 
ON UPDATE RESTRICT
ON DELETE RESTRICT

当我使用以下 SQL-代码调用 table tasks 时:

SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
JOIN worker AS b ON a.shop_worker = b.id
JOIN worker AS c ON a.production_worker = c.id

结果是:

+----+------+----------+-------------+----------------+-------------------+----
| id | task | shop_req | shop_worker | production_req | production_worker | ...
+----+------+----------+-------------+----------------+-------------------+----

表示结果只有列名,没有行。
我希望得到以下结果:

+----+------------+----------+-------------+----------------+-------------------+----
| id | task       | shop_req | shop_worker | production_req | production_worker | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 1  | do sth.    | yes      | bar, foo    | yes            | baz, foo          | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 2  | do sth.    | no       | (NULL)      | yes            | baz, foo          | ...
...

这里有什么问题?我找不到错误。
有没有有效的方法调用SQL-代码?

非常感谢您的回答!

首先,您的查询缺少 tasksAS a 别名,这会使查询失败。添加后,您应该返回一行,但是 ...

因为您想要包含 tasks table 中的所有行,即使 shop_workerproduction_worker 没有匹配的行,您也需要使用left join 而不是像这样:

SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
LEFT JOIN worker AS b ON a.shop_worker = b.id
LEFT JOIN worker AS c ON a.production_worker = c.id

Sample SQL Fiddle

有关各种联接的详细介绍,请参阅:A Visual Explanation of SQL Joins

您需要 left join 而不是 inner join

SELECT 
a.id, 
a.task,
a.shop_req, 
CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, 
CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks a
left join worker b ON a.shop_worker = b.id
left join worker c ON a.production_worker = c.id