我正在使用SQLAlchemy作为我的ORM实现与MySQL的聊天系统
我的表格包含以下列:id, from_user_id, to_user_id, message, time_sent.
我正在尝试创建一个查询,在其中我选择包含每个会话发送的最新消息的记录。这就像人们在Facebook上看到的对话列表一样。
关于如何做到这一点的任何想法?
以下是我到目前为止的情况:
latest_msg_sq = (DBSession.query(func.max(Message.id).label("max_id"))
.group_by(Message.from_user)).subquery()
matching_conv = DBSession.query(Message)
.join(latest_msg_sq, and_(Message.id ==
latest_msg_sq.c.max_id)).order_by(Message.time_sent.desc())
不幸的是,它不能很好地工作,因为它只获取from_user_id的最新消息。我需要它来考虑来自to_user_id的消息,而group_by似乎不是最好的方法。在我看来,我认为我需要将记录from_user_id和to_user_id视为无序对,然后在这些对上使用group_by。但是,我不知道该怎么做。
答案 0 :(得分:1)
在MySQL中,您可以使用least()
和greatest()
。要获得最近的时间:
select least(from_user_id, to_user_id) as u1, greatest(from_user_id, to_user_id) as u2,
max(time_sent) as maxts
from messages
group by least(from_user_id, to_user_id), greatest(from_user_id, to_user_id)
要获取完整的消息,您可以将其加入:
select m.*
from (select least(from_user_id, to_user_id) as u1, greatest(from_user_id, to_user_id) as u2,
max(time_sent) as maxts
from messages
group by least(from_user_id, to_user_id), greatest(from_user_id, to_user_id)
) m2 join
messages m
on least(m2.from_user_id, m2.to_user_id) = least(m.from_user_id, m.to_user_id) and
greatest(m2.from_user_id, m2.to_user_id) = greatest(m.from_user_id, m.to_user_id)
我不确定你会如何在SQLalchemy中表达这一点。
答案 1 :(得分:1)
试试这个:
select msg1.* from message msg1
left outer join message msg2 on
(msg1.from_user_id = msg2.from_user_id
and msg1.to_user_id = msg2.to_user_id and msg2.time_sent > msg1.time_sent)
left outer join message msg3 on
msg1.to_user_id = msg3.from_user_id
and msg1.from_user_id= msg3.to_user_id and msg3.time_sent > msg1.time_sent
where msg2.id is null and msg3.id is null
答案 2 :(得分:1)
Mohnsen Heydari的SQLAlchemy版本为所有需要它的人提供了答案:
msg1 = aliased(Message)
msg2 = aliased(Message)
msg3 = aliased(Message)
matching_conv = DBSession.query(msg1)
matching_conv = matching_conv.outerjoin(msg2, and_(msg1.from_user==msg2.from_user, msg1.to_user==msg2.to_user, msg2.id > msg1.id))
matching_conv = matching_conv.outerjoin(msg3, and_(msg1.to_user==msg3.from_user, msg1.from_user==msg3.to_user, msg3.id > msg1.id))
matching_conv = matching_conv.filter(and_(msg2.id == None, msg3.id == None)).order_by(msg1.time_sent.desc())