Reputation: 191
I have a table, meeting
. Among these meeting
s there exists a hierarchy. Some of them are yearly meetings, most are just regular meetings.
All regular meetings
will be associated with at least one join table, meeting_yearly_meeting
. A meeting_yearly_meeting
has two columns: meeting_id
and yearly_meeting_id
.
Here is what these two tables look like:
meeting:
id SERIAL PRIMARY KEY,
title VARCHAR(255),
mappable BOOLEAN,
phone VARCHAR(255),
email VARCHAR(255),
city VARCHAR(255),
address VARCHAR(255),
zip VARCHAR(255),
latitude NUMERIC,
longitude NUMERIC,
description VARCHAR(255),
worship_time TIME,
state VARCHAR(255),
website VARCHAR(255),
lgbt_affirming BOOLEAN,
created TIMESTAMP default current_timestamp,
updated TIMESTAMP default current_timestamp
meeting_yearly_meeting:
id SERIAL PRIMARY KEY,
meeting_id SMALLINT,
yearly_meeting_id SMALLINT,
created TIMESTAMP default current_timestamp,
updated TIMESTAMP default current_timestamp
So from my /meetings
endpoint, I want to return a collection of all meetings - both regular and yearly meetings. I want to return the meetings with all their columns, as well as an additional column: yearly_meeting
.
For meeting
records that have one or more associated meeting_yearly_meeting
records, yearly_meeting
would be a comma-delimited list of the title
of the meeting
record that is designated as that meeting
's yearly meeting. For those meetings that do not have any associated meeting_yearly_meeting
records (and therefore are themselves yearly meetings), I want the yearly_meeting field to be
NULL`.
On my way to pursuing this goal, I tried something like this:
SELECT t1.*, t2.meeting_yearly_meeting AS yearly_meeting
FROM (
SELECT * FROM meeting
FULL JOIN meeting_yearly_meeting ON meeting.id = meeting_yearly_meeting.yearly_meeting_id;
) as t1,
(
SELECT CASE WHEN (meeting_yearly_meeting.id IS NOT NULL)
THEN (SELECT title FROM meeting WHERE meeting.id = meeting_yearly_meeting.yearly_meeting_id)
ELSE NULL
END
FROM (
SELECT meeting_yearly_meeting.* FROM meeting
FULL JOIN meeting_yearly_meeting ON meeting.id = meeting_yearly_meeting.meeting_id
) as meeting_yearly_meeting;
) as t2;
But this throws a syntax error.
I appreciate any insight others might have. Please let me know if there is any additional context or clarification you need!
UPDATE:
Sample meeting
data: https://gist.github.com/micahbales/4013399c3fd23a0caf108124dab827c8
Sample meeting_yearly_meeting
data: https://gist.github.com/micahbales/fcbdeef282bd7bf1014606cee43bfb5e
Expected return value example: https://gist.github.com/micahbales/13d2aafdc5d43c4b948dc39c2df51569
Upvotes: 1
Views: 72
Reputation: 37467
You can try to left join the yearly meetings and then use string_agg()
to get your comma delimited list.
SELECT m1.id,
m1.title,
m1.mappable,
m1.phone,
m1.email,
m1.city,
m1.address,
m1.zip,
m1.latitude,
m1.longitude,
m1.description,
m1.worship_time,
m1.state,
m1.website,
m1.lgbt_affirming,
m1.created,
m1.updated,
string_agg(m2.title, ', ') yearly_meeting
FROM meeting m1
LEFT JOIN meeting_yearly_meeting mym1
ON mym1.meeting_id = m1.id
LEFT JOIN meeting m2
ON m2.id = mym1.yearly_meeting_id
GROUP BY m1.id,
m1.title,
m1.mappable,
m1.phone,
m1.email,
m1.city,
m1.address,
m1.zip,
m1.latitude,
m1.longitude,
m1.description,
m1.worship_time,
m1.state,
m1.website,
m1.lgbt_affirming,
m1.created,
m1.updated;
Edit:
A more "compact" solution could be using a correlated subquery.
SELECT m1.*,
(SELECT string_agg(m2.title, ', ')
FROM meeting_yearly_meeting mym1
LEFT JOIN meeting m2
ON m2.id = mym1.yearly_meeting_id
WHERE mym1.meeting_id = m1.id) yearly_meeting
FROM meeting m1;
But note, though it's less code, it's not necessarily faster.
Upvotes: 1