簡體   English   中英

如何在 SQL 中查詢表的層次結構

[英]How to Query A Hierarchy of Tables in SQL

我有一張桌子, meeting 在這些meeting之間存在着等級制度。 其中一些是年度會議,大多數只是定期會議。

所有定期meetings都將與至少一個連接表相關聯, meeting_yearly_meeting 一個meeting_yearly_meeting有兩列: meeting_idyearly_meeting_id

下面是這兩個表的樣子:

會議:

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

因此,從我的/meetings端點,我想返回所有會議的集合 - 定期會議和年度會議。 我想返回會議及其所有列,以及一個附加列: yearly_meeting

對於具有一個或多個關聯meeting_yearly_meeting記錄的meeting記錄, yearly_meeting將是指定為該meeting的年度會議的meeting記錄title的逗號分隔列表。 對於那些沒有任何關聯的meeting_yearly_meeting記錄的會議(因此它們本身就是年度會議),我希望yearly_meeting field to be NULL`。

在我追求這個目標的路上,我嘗試了這樣的事情:

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;

但這會引發語法錯誤。

我很欣賞其他人可能有的任何見解。 如果您需要任何其他上下文或說明,請告訴我!

更新:

示例meeting數據: https : //gist.github.com/micahbales/4013399c3fd23a0caf108124dab827c8

樣本meeting_yearly_meeting數據: https : meeting_yearly_meeting

預期返回值示例: https : //gist.github.com/micahbales/13d2aafdc5d43c4b948dc39c2df51569

您可以嘗試離開參加年度會​​議,然后使用string_agg()獲取逗號分隔的列表。

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;

編輯:

更“緊湊”的解決方案可能是使用相關子查詢。

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;

但請注意,雖然代碼較少,但不一定更快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM