在Postgres中联接同一表的路径不止一个

ere*_*ere 7 sql postgresql join left-join

我继承了一些要清理的表,但首先,我试图加入所需的所有内容,但是遇到了问题,因为SpecialEvents通过表到达表的方法不止一种EventRegistrations

在某些情况下EventRegistrations可以直接使用连接,event_registrations.scoreable_id而在另一些情况下则必须先连接另一个表SpecialPlaces,您可以知道需要通过event_registrations.scoreable_type哪种方式为SpecialEventor或SpecialPlace

基本上,SpecialEvents如果我还必须SpecialPlaces先加入,该如何加入?例如,如果我尝试以SpecialEvents两种不同的方式加入,则会出现错误:“表名“ special_events”指定了多次。

SELECT event_registrations.id, array_agg(teams.name), event_registrations.number_of_players, event_registrations.state, event_registrations.created_at, array_agg(players.email), array_agg(special_events.name), array_agg(special_places.id)
FROM event_registrations
LEFT JOIN teams ON event_registrations.team_id = teams.id
LEFT JOIN team_memberships ON teams.id = team_memberships.team_id
LEFT JOIN players ON team_memberships.player_id = players.id
LEFT JOIN special_events ON event_registrations.scoreable_id = special_events.id AND event_registrations.scoreable_type = 'SpecialEvent'
LEFT JOIN special_places ON event_registrations.scoreable_id = special_places.id AND event_registrations.scoreable_type = 'SpecialPlace'
GROUP BY event_registrations.id, event_registrations.number_of_players, event_registrations.state, event_registrations.created_at
Run Code Online (Sandbox Code Playgroud)

特别活动

+----+-----------+---------------------------+-----------+---------------------------+
| id | region_id | start_at                  | state     | created_at                |
+----+-----------+---------------------------+-----------+---------------------------+
| 2  | 1         | 2015-10-22 19:30:00 +0100 | published | 2015-09-21 09:41:05 +0100 |
| 4  | 1         | 2016-01-21 19:30:00 +0000 | published | 2015-11-26 15:11:25 +0000 |
| 3  | 1         | 2016-01-28 19:30:00 +0000 | published | 2015-11-23 16:16:27 +0000 |
| 5  | 1         | 2016-12-31 19:30:00 +0000 | draft     | 2016-02-24 15:17:22 +0000 |
| 6  | 1         | 2016-05-16 19:30:00 +0100 | published | 2016-03-29 14:33:40 +0100 |
| 10 | 1         | 2016-09-12 19:30:00 +0100 | published | 2016-06-28 17:18:54 +0100 |
| 8  | 1         | 2016-10-07 19:30:00 +0100 | draft     | 2016-06-09 15:03:36 +0100 |
| 7  | 1         | 2016-05-23 19:30:00 +0100 | published | 2016-03-30 19:30:21 +0100 |
| 9  | 1         | 2016-08-04 19:30:00 +0100 | published | 2016-06-09 15:18:56 +0100 |
| 11 | 1         | 2016-11-07 19:30:00 +0000 | draft     | 2016-07-11 17:20:11 +0100 |
+----+-----------+---------------------------+-----------+---------------------------+
Run Code Online (Sandbox Code Playgroud)

特殊地方

+----+------------------+----------+---------------------------+
| id | special_event_id | place_id | created_at                |
+----+------------------+----------+---------------------------+
| 1  | 2                | 243      | 2015-10-12 18:07:09 +0100 |
| 3  | 2                | 83       | 2015-10-15 15:54:40 +0100 |
| 5  | 4                | 262      | 2015-11-26 16:29:35 +0000 |
| 4  | 3                | 262      | 2015-11-23 16:25:31 +0000 |
| 6  | 5                | 281      | 2016-02-24 15:20:33 +0000 |
| 7  | 6                | 262      | 2016-03-29 14:34:00 +0100 |
| 8  | 7                | 262      | 2016-04-11 13:28:00 +0100 |
| 9  | 8                | 262      | 2016-06-09 15:03:52 +0100 |
| 12 | 11               | 262      | 2016-07-11 17:20:26 +0100 |
| 10 | 9                | 262      | 2016-06-09 15:20:08 +0100 |
+----+------------------+----------+---------------------------+
Run Code Online (Sandbox Code Playgroud)

活动注册

+----+---------+--------------+----------------+-------+---------------------------+
| id | team_id | scoreable_id | scoreable_type | state | created_at                |
+----+---------+--------------+----------------+-------+---------------------------+
| 1  | 3979    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 2  | 3717    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 3  | 3626    | 8            | SpecialPlace   | draft | 2015-11-30 10:09:06 +0000 |
| 4  | 3202    | 8            | SpecialPlace   | draft | 2015-11-30 10:09:06 +0000 |
| 5  | 703     | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 6  | 278     | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 7  | 3166    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 8  | 3147    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 9  | 3146    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
| 10 | 3145    | 2            | SpecialEvent   | draft | 2015-11-30 10:09:06 +0000 |
+----+---------+--------------+----------------+-------+---------------------------+
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

hol*_*den 6

我的同事想说的是,您想要做的方式是不可行的,但是,做同一件事的方法有很多。

要避免两次联接,您可以做的是创建一个包含SpecialEvents和SpecialPlaces的组合表,其中包含您想要的所有信息,然后进行联接。

例如这样的事情:

SELECT event_registrations.id, array_agg(teams.name), event_registrations.number_of_players, event_registrations.state, event_registrations.created_at, array_agg(players.email), array_agg(special_events.name), array_agg(special_places.id)
FROM event_registrations
LEFT JOIN teams ON event_registrations.team_id = teams.id
LEFT JOIN team_memberships ON teams.id = team_memberships.team_id
LEFT JOIN players ON team_memberships.player_id = players.id
LEFT JOIN special_places ON event_registrations.scoreable_id = special_places.id AND event_registrations.scoreable_type = 'SpecialPlace'
LEFT JOIN (
SELECT special_events.id AS special_event_id, special_places.id AS special_place_id, special_events.name
FROM special_places
LEFT JOIN special_events ON special_places.special_event_id = special_events.id
UNION
SELECT special_events.id AS special_event_id, null AS special_place_id, special_events.name
FROM special_events
) el1
ON (event_registrations.scoreable_id = el1.special_place_id AND event_registrations.scoreable_type = 'SpecialPlace') OR (event_registrations.scoreable_id = el1.special_event_id AND event_registrations.scoreable_type = 'SpecialEvent')
GROUP BY event_registrations.id, event_registrations.number_of_players, event_registrations.state, event_registrations.created_at
Run Code Online (Sandbox Code Playgroud)