【问题标题】:Postgres query to find if combination already exist in junction tablePostgres查询以查找连接表中是否已存在组合
【发布时间】:2020-03-05 16:12:20
【问题描述】:

我有一个简单的聊天模块,允许帐户创建多用户房间。

  • 鉴于以下架构 - 是否可以创建一个查询来检查给定用户的房间是否已经存在?

  • 如果此检查可能导致性能问题 - 您能否提出其他设计或方法?

示例数据:

- chat_id: 1, users: [1, 2, 3]
- chat_id: 2, users: [2, 3]
- chat_id: 3, users: [1]
- chat_id: 4, users: [5, 6]

所需查询:

Check if chat room for users [2, 3] exists => true, id: 2
Check if chat room for users [1, 2, 3] exists => true, id: 1
Check if chat room for users [2, 6] exists => false
Check if chat room for users [1, 2, 6] exists => false

我正在使用 postgres 11.2

编辑: 如果存在给定的组合,我也应该能够获取聊天 ID。

【问题讨论】:

    标签: sql postgresql database-design chat junction-table


    【解决方案1】:

    我认为这是你想要的:

    select ca.chat_id
    from chat_account ca
    group by ca.chat_id
    having count(*) filter (where account_id in (2, 3)) = 2 and
           count(*) = 2;
    

    你也可以使用:

    having array_agg(account_id order by account_id) = array[2, 3]
    

    【讨论】:

    • 看起来它在你最后一次修复后工作。你能解释一下为什么吗?我也很好奇这个的表现,因为没有任何 where 子句。它不会查询表中的所有行吗?
    • @milo 。 . .嗯,是。它需要查询所有行。这是好是坏取决于您的数据大小以及您想要的值列表的比例。
    【解决方案2】:

    你需要这样的东西

    with selected_users as (select * from accounts where id in (2,3)),
    users_chat_rooms as (
    select chat_id,
    array_agg(account_id order by account_id asc) users_in_room
    from chat_account
    group by chat_id
    )
    select * from users_chat_rooms
    where chat_id in (select chat_id from chat_account where account_id in (select id from selected_users))
    and users_in_room = (select array_agg(id order by id asc) from selected_users)
    
    

    见小提琴https://dbfiddle.uk/?rdbms=postgres_11&fiddle=f360a05c57a33f5c130fcfa0d55429ff

    您可能会将其显示给特定用户,因此您可以过滤“登录”用户的聊天记录。

    select * from users_chat_rooms
    where chat_id in (select chat_id from chat_account where account_id = <logged_in_user>)
    and users_in_room = (select array_agg(id order by id asc) from selected_users)
    
    

    【讨论】:

      【解决方案3】:

      根据其他答案,我最终编写了自己的查询:

      SELECT chat_id FROM chat_account
      WHERE chat_id IN (
          SELECT c2.chat_id
          FROM chat_account c2
          WHERE c2.account_id IN (2, 3)
      )
      GROUP BY chat_account.chat_id
      HAVING array_agg(chat_account.account_id) = ARRAY[2, 3]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-05
        • 2015-03-22
        • 2017-03-24
        • 2015-09-23
        • 2019-07-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多