Postgres 多对多:如何 select 记录精确计数的链接
Postgres many to many: how to select record with exactly counted links
使用该架构(当然还有更多字段)我想 select 确切地聊天,其中 clients.id 例如 344,345,它们正好是两个。
但我找到了所有与其他客户聊天的地方,而不仅仅是他们两个。
(来源:zimagez.com)
大图http://www.zimagez.com/zimage/107410861087108810861089-10871086-habtm0.php
SELECT
chat_rooms.id,
chat_rooms.token
FROM
chat_rooms,
clients,
chat_rooms_clients
WHERE
chat_rooms_clients.chat_room_id = chat_rooms.id AND
chat_rooms_clients.client_id = clients.id AND
clients.id IN (344,354) AND
chat_rooms.meeting_id IS NULL
group by chat_rooms.id
having count(clients.id) = 2
ORDER BY
chat_rooms.created_at DESC;
我的应用程序是用 rails 编写的。
使用提供的测试数据:
set search_path = testschema, pg_catalog;
select cr.id, array_agg(crc.client_id order by crc.client_id), cr.token
from
chat_rooms_clients crc
inner join
chat_rooms cr on cr.id = crc.chat_room_id
where cr.meeting_id is null
group by 1
having array_agg(crc.client_id order by crc.client_id) = array[2467,2471]::int[]
order by cr.created_at desc;
id | array_agg | token
-----+-------------+--------------------------------------
234 | {2467,2471} | bd36db10-3a89-40fe-a3e3-524b4278b718
请注意,对于此查询,没有必要加入 clients
table。我认为在 chat_rooms_clients
table:
中创建一个主键是明智的
create table chat_rooms_clients (
chat_room_id integer not null,
client_id integer not null,
primary key (chat_room_id, client_id)
);
否则为了保险起见,需要在上面查询的array_agg
中加上distinct
:
having array_agg(distinct crc.client_id order by crc.client_id) = ...
如果聊天室创建者必须是聊天参与者之一,则对其进行过滤以提高性能:
where cr.meeting_id is null and cr.creator_id in (2467,2471)
使用该架构(当然还有更多字段)我想 select 确切地聊天,其中 clients.id 例如 344,345,它们正好是两个。
但我找到了所有与其他客户聊天的地方,而不仅仅是他们两个。
(来源:zimagez.com)
大图http://www.zimagez.com/zimage/107410861087108810861089-10871086-habtm0.php
SELECT
chat_rooms.id,
chat_rooms.token
FROM
chat_rooms,
clients,
chat_rooms_clients
WHERE
chat_rooms_clients.chat_room_id = chat_rooms.id AND
chat_rooms_clients.client_id = clients.id AND
clients.id IN (344,354) AND
chat_rooms.meeting_id IS NULL
group by chat_rooms.id
having count(clients.id) = 2
ORDER BY
chat_rooms.created_at DESC;
我的应用程序是用 rails 编写的。
使用提供的测试数据:
set search_path = testschema, pg_catalog;
select cr.id, array_agg(crc.client_id order by crc.client_id), cr.token
from
chat_rooms_clients crc
inner join
chat_rooms cr on cr.id = crc.chat_room_id
where cr.meeting_id is null
group by 1
having array_agg(crc.client_id order by crc.client_id) = array[2467,2471]::int[]
order by cr.created_at desc;
id | array_agg | token
-----+-------------+--------------------------------------
234 | {2467,2471} | bd36db10-3a89-40fe-a3e3-524b4278b718
请注意,对于此查询,没有必要加入 clients
table。我认为在 chat_rooms_clients
table:
create table chat_rooms_clients (
chat_room_id integer not null,
client_id integer not null,
primary key (chat_room_id, client_id)
);
否则为了保险起见,需要在上面查询的array_agg
中加上distinct
:
having array_agg(distinct crc.client_id order by crc.client_id) = ...
如果聊天室创建者必须是聊天参与者之一,则对其进行过滤以提高性能:
where cr.meeting_id is null and cr.creator_id in (2467,2471)