我正在使用一个关系数据库,其中有如下数据:
messages sender receiver
[1,2,3] | A | B
[4,5,6] | C | D
[7,8,9] | D | C
[10,11,12] | B | A
我需要像这样在完整的对话中将单独的消息分组:
conversation participant_1 particiapant_2
[1,2,3, 10, 11, 12] | A | B -- order of participants does not matter
[4,5,6, 7,8,9] | C | D
我想到了两个可行的解决方案:
messages p_1 p_2
[1,2,3] | A | B
[4,5,6] | C | D
[7,8,9] | D | C
[10,11,12] | B | A
[1,2,3] | B | A
[4,5,6] | D | C
[7,8,9] | C | D
[10,11,12] | A | B
最后按p_1或p_2分组并在元素数组上使用和聚合函数将产生结果。
messages sender receiver id
[1,2,3] | A | B | 1
[4,5,6] | C | D | 2
[7,8,9] | D | C | 2
[10,11,12] | B | A | 1
按ID分组将使我在发送方和接收方列中使用聚合函数,因为否则分组将失败。因此,我认为解决方案1会更好。
但是,我不知道如何用SQL很好地表达这些解决方案。还是对此有更好,更优化的解决方案?如果是这样,您怎么能解决这样的问题?
编辑:原始表的架构是这样的:
message from to message_sid
"message 1" | A | B | "SM716241"
"message 2" | A | B | "SM762415"
"test" | B | A | "SM723741"
reply | C | D | "SM142469"
我以第一个表的形式提出的查询是这样的:
select json_agg(json_build_object('message', body, 'date', date_sent, 'direction', direction)),
message.from as sender,
message.to as receiver
from message
group by message.from, message.to;
我放置了一个更简化的模式版本,以使其更易于理解。该查询还包括日期和消息方向(入站或出站),但它们对于问题不是必需的。
您可以使用'A'<'B'来交换它们的事实,例如:
SELECT
CASE WHEN sender < receiver THEN sender ELSE receiver END as participant1,
CASE WHEN sender < receiver THEN receiver ELSE sender END as participant2
然后对您的消息ID进行字符串结尾(或者是存储您的消息,我不太理解问题中消息ID的表示形式)。这意味着您无需繁琐的“ x / y联合y / x”即可获得一致的“对话方列表”
另外,在PGSQL中,您拥有可以实现相同功能的GREATEST和LEAST函数:
SELECT
LEAST(sender, receiver) as participant1,
GREATEST(sender, receiver) as participant2
select json_agg(json_build_object('message', body, 'date', date_sent, 'direction', direction)),
GREATEST(message.from,message.to) as party1,
LEAST(message.from,message.to) as party2
from message
group by GREATEST(message.from, message.to), LEAST(message.from, message.to) ;
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句