内部联接不必要地删除了一些行
Inner join removes some rows unnecessarily
我有 3 个表这样定义
CREATE TABLE participants(
id SERIAL PRIMARY KEY,
Name TEXT NOT NULL,
Title TEXT NOT NULL
);
CREATE TABLE meetings (
id SERIAL PRIMARY KEY,
Subject TEXT NOT NULL,
Organizer TEXT NOT NULL,
StartTime TIMESTAMP NOT NULL,
EndTime TIMESTAMP NOT NULL
);
CREATE TABLE meetings_participants(
meeting_id int not null,
participant_id int not null,
primary key (meeting_id, participant_id),
foreign key(meeting_id) references meetings(id),
foreign key(participant_id) references participants(id)
);
我想查找今天与参与者一起举行的会议。
当我 运行 这个查询时,我基本上得到了它们
SELECT * from meetings
INNER JOIN meetings_participants ON meetings.id = meetings_participants.meeting_id
INNER JOIN participants ON meetings_participants.participant_id = participants.id
WHERE starttime::date = NOW()::date;
问题是此查询会丢弃还没有参与者的会议,我仍然希望将它们包含在我的查询结果中。我怎样才能修改我的查询以像那样工作?
您需要 LEFT JOIN 而不是 INNER。使用 ::date 铸造你是在暗示你只对今天发生的事情感兴趣,不管它是否已经结束。您仍然应该在查询中包含 EndTime,考虑到可能会有跨越数天的会议:[=14=]
SELECT * from meetings
left join meetings_participants on meetings.id = meetings_participants.meeting_id
left join participants on meetings_participants.participant_id = participants.id
WHERE starttime::date <= NOW()::date and endtime::date >= NOW()::date ;
编辑:参与者的姓名和头衔作为 JSON 数组:
SELECT id, subject, organizer, starttime, endtime, jsonb_pretty(tmp.participants)
from meetings m
left join lateral (
select jsonb_agg(row_to_json(tp)) as participants
from (select p.name, p.title
from meetings_participants mp
inner join participants p on mp.participant_id = p.id
where mp.meeting_id = m.id
) tp
) tmp on true
WHERE starttime::date <= NOW()::date
and endtime::date >= NOW()::date;
您没有提到您是希望每个参与者在单独的行中还是作为一个集合(例如,逗号分隔列表)。如果是前者,则将内部连接更改为左连接。对于后一种情况,您可以:
SELECT meetings.*, (
SELECT string_agg(participants.name, ', ')
FROM meetings_participants
JOIN participants ON meetings_participants.participant_id = participants.id
WHERE meetings_participants.meeting_id = meetings.id
) AS participants_list
FROM meetings
WHERE starttime::date = current_date
我有 3 个表这样定义
CREATE TABLE participants(
id SERIAL PRIMARY KEY,
Name TEXT NOT NULL,
Title TEXT NOT NULL
);
CREATE TABLE meetings (
id SERIAL PRIMARY KEY,
Subject TEXT NOT NULL,
Organizer TEXT NOT NULL,
StartTime TIMESTAMP NOT NULL,
EndTime TIMESTAMP NOT NULL
);
CREATE TABLE meetings_participants(
meeting_id int not null,
participant_id int not null,
primary key (meeting_id, participant_id),
foreign key(meeting_id) references meetings(id),
foreign key(participant_id) references participants(id)
);
我想查找今天与参与者一起举行的会议。 当我 运行 这个查询时,我基本上得到了它们
SELECT * from meetings
INNER JOIN meetings_participants ON meetings.id = meetings_participants.meeting_id
INNER JOIN participants ON meetings_participants.participant_id = participants.id
WHERE starttime::date = NOW()::date;
问题是此查询会丢弃还没有参与者的会议,我仍然希望将它们包含在我的查询结果中。我怎样才能修改我的查询以像那样工作?
您需要 LEFT JOIN 而不是 INNER。使用 ::date 铸造你是在暗示你只对今天发生的事情感兴趣,不管它是否已经结束。您仍然应该在查询中包含 EndTime,考虑到可能会有跨越数天的会议:[=14=]
SELECT * from meetings
left join meetings_participants on meetings.id = meetings_participants.meeting_id
left join participants on meetings_participants.participant_id = participants.id
WHERE starttime::date <= NOW()::date and endtime::date >= NOW()::date ;
编辑:参与者的姓名和头衔作为 JSON 数组:
SELECT id, subject, organizer, starttime, endtime, jsonb_pretty(tmp.participants)
from meetings m
left join lateral (
select jsonb_agg(row_to_json(tp)) as participants
from (select p.name, p.title
from meetings_participants mp
inner join participants p on mp.participant_id = p.id
where mp.meeting_id = m.id
) tp
) tmp on true
WHERE starttime::date <= NOW()::date
and endtime::date >= NOW()::date;
您没有提到您是希望每个参与者在单独的行中还是作为一个集合(例如,逗号分隔列表)。如果是前者,则将内部连接更改为左连接。对于后一种情况,您可以:
SELECT meetings.*, (
SELECT string_agg(participants.name, ', ')
FROM meetings_participants
JOIN participants ON meetings_participants.participant_id = participants.id
WHERE meetings_participants.meeting_id = meetings.id
) AS participants_list
FROM meetings
WHERE starttime::date = current_date