Mysql从三个表连接数据(多对多关系)

时间:2018-02-06 18:31:45

标签: mysql sql many-to-many relationship

这是我的mysql数据库架构:

db schema 我想创建一个查询,以下列方式返回有关所有培训的数据:

training。*,[type.type],[voivodeship.name] 如果没有与给定训练相关的类型或省级,则应在列值中返回null。

例如:

 {
    "id": 1,
    "name": "Example training 2",
    "description": "This is a description 2",
    "status": "status 2",
    "registerFrom": null,
    "registerTo": null,
    "DateOfInsert": "2018-02-06T12:00:57.000Z",
    "training types": "Example type 1,Example type 3,Example type 2"
    "localizations": "loc 1, loc 3"
 },
...
 {
    "id": 99,
    "name": "Example training 99",
    "description": "This is a description 99",
    "status": "status 2",
    "registerFrom": null,
    "registerTo": null,
    "DateOfInsert": "2018-02-06T12:00:57.000Z",
    "training types": null,
    "localizations": null
 },
 {
    "id": 99,
    "name": "Example training 99",
    "description": "This is a description 99",
    "status": "status 2",
    "registerFrom": null,
    "registerTo": null,
    "DateOfInsert": "2018-02-06T12:00:57.000Z",
    "training types": "Example type 9,Example type 4,Example type 2",
    "localizations": "loc 56, loc 32"
  },

这是我当前的查询,返回有关其本地化的信息的训练(遗憾的是它没有返回没有它们的那些),我也不知道如何修改它以返回所有类型:

SELECT `training`.*, GROUP_CONCAT(`voivodeship`.`name`) AS `Localizations`
FROM `training_localization` 
INNER JOIN `training` ON (`training_localization`.`training_id` = `training`.`id`) 
INNER JOIN `voivodeship` ON (`training_localization`.`voivodeship_id` = `voivodeship`.`id`) 
GROUP BY `training`.`id`

我对sql不是很有经验。甚至可以使用一个查询吗?

根据戈登的回答,我提出了新的查询,看起来它正在起作用:):

SELECT t.*, GROUP_CONCAT(vs.name) AS Localizations,  tw.types AS types
FROM training t 
     LEFT JOIN training_localization tl ON tl.training_id = t.id 
     LEFT JOIN voivodeship vs ON tl.voivodeship_id = vs.id
     LEFT JOIN(
        SELECT t.*, GROUP_CONCAT(ty.type) AS Types
        FROM training t 
             LEFT JOIN training_type tt ON tt.training_id = t.id 
             LEFT JOIN type ty ON tt.type_id = ty.id
        GROUP BY t.id
        ) tw ON tw.id = t.id
GROUP BY t.id;

1 个答案:

答案 0 :(得分:1)

如果你想要所有的东西,请考虑“外部联接”。如果您想要所有培训,那应该是left join s系列中的第一个表:

SELECT t.*, GROUP_CONCAT(vs.name) AS Localizations
FROM training t LEFT JOIN
     training_localization tl
     ON tl.training_id = t.id LEFT JOIN 
     voivodeship vs
     ON tl.voivodeship_id = vs.id
GROUP BY t.id;

注意:

  • LEFT JOIN将所有内容保存在第一个表中并匹配后续表中的行(除非使用内部联接或where子句撤消它)。
  • 表别名使查询更易于编写和阅读。
  • 消除不必要的反引号使查询更容易编写和阅读。