SQL 中的等效集

问题描述 投票:0回答:1

我正在创建一个基于群组的聊天,该聊天要求仅将消息发送给同一群组中的人员。莎拉、詹姆斯和克里斯属于一个组,但不是莎拉、詹姆斯、克里斯和保罗,也不是莎拉和詹姆斯。到目前为止,我是这样建模的:

这是表A,它将把user_id链接到group_id

user_id|group_id
   1   |   1
   2   |   1
   1   |   2
   2   |   2
   3   |   2

这是表 B,它被存储过程接受为输入

sender_id|recipient_id|text 
    1    |     2      | Hey 
    1    |     3      | Hey 

表 B 代表一条消息,因此 sender_idtext 将相同。这意味着 user_ids 1、2 和 3 位于同一群组对话中,但不是 1 和 2 或 1 和 3。

现在这是棘手的部分。我事先不知道消息本身的 group_id,这是因为从上面的两个表中,需要动态确定该消息是否将分配给现有组(意味着 group_id 存在于 中)表 A 包含 表 B 中的确切 user_ids),或者是否需要创建新组(没有完全匹配)。

这是包含消息的表

group_id|sender_id|message_id|text
   ?    |     1   |   ...    |Hey

关于如何根据表 A 和 B 确定是否需要创建新的 group_id 有什么建议吗?

sql sql-server relational-database set-theory
1个回答
0
投票

我可能会通过发件人+收件人的联合在消息中构建一组用户来解决这个问题,然后将它们与现有组进行匹配并确保数字完全匹配。

类似:

WITH incoming AS (
    SELECT  *
    FROM
    (
        VALUES  (1, 2, N'Hey')
        ,   (1, 3, N'Hey')
    ) t (sender_id,recipient_id,text)
)
, incoming_group AS (

    
    SELECT  vd.sender_id, COUNT(*) OVER() AS cnt
    FROM    incoming v
    CROSS apply (
        VALUES(sender_id),(recipient_id)
        ) vd
    GROUP BY vd.sender_id
    )
, existing AS (
    SELECT  *
    FROM
        (
        VALUES  (1, 1)
        ,   (2, 1)
        ,   (1, 2)
        ,   (2, 2)
        ,   (3, 2)
    ) t (user_id,group_id)
)
, existing_group as (
    SELECT  user_id, group_id
    ,   COUNT(*) OVER(PARTITION BY group_id) AS cnt
    FROM    existing
)
SELECT  eg.group_id AS matching_group
FROM    incoming_group ig
LEFT JOIN existing_group eg
    ON  eg.user_id = ig.sender_id
    AND eg.cnt = ig.cnt
GROUP BY eg.group_id, ig.cnt
HAVING COUNT(*) = ig.cnt
  1. 构建传入_组,用于计算传入消息中有多少用户,这是发件人和所有收件人的组合
  2. 构建与上面类似的现有组,其中包含每个现有组的用户数量
  3. 在此期间加入并确保计数与用户匹配。

如果加入成功,您将获得现有的组ID,否则您将获得0行并可以创建新组等

© www.soinside.com 2019 - 2024. All rights reserved.