Python SQL:如何将两列分组为无序对?
我正在用MySQL实现一个聊天系统,使用SQLAlchemy作为我的ORM。Python SQL:如何将两列分组为无序对?,python,mysql,sql,sqlalchemy,Python,Mysql,Sql,Sqlalchemy,我正在用MySQL实现一个聊天系统,使用SQLAlchemy作为我的ORM。 我的表格有以下列:id、from\u user\u id、to\u user\u id、message、time\u sent. 我正在尝试创建一个查询,在该查询中,我选择包含每个对话发送的最新消息的记录。这与人们在Facebook上看到的对话列表一模一样 有什么办法吗? 以下是我到目前为止的情况: latest_msg_sq = (DBSession.query(func.max(Message.id).label(
我的表格有以下列:
id、from\u user\u id、to\u user\u id、message、time\u 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())
不幸的是,它工作得不是很好,因为它只获取了FasuxUsRyId的最新消息。我需要它也考虑来自TouUsSeriID的消息,而GypPyBy似乎不是最好的方法。在我看来,我认为我需要考虑从UsUrSyID和ToUsUrthIID作为无序对的记录,然后在这些对上使用GROPYBY。但是,我不知道怎么做。
在MySQL中,您将使用least()
和grest()
。要获取最近的时间,请执行以下操作:
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中表达这一点。试试这个: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
SQLAlchemy版Mohsen Heydari的答案适用于任何需要它的人:
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())
关于如何在SQLAlchemy中实现这一点,有什么想法吗?它们是简单的左连接。我不熟悉SQLAlchemy,但任何支持左joinsChat的ORM应用程序通常都有一个房间抽象,它使用自己的唯一id实现。与其尝试将
从用户id加上到用户id
转换为对话,如果您的messages
表中有以下列可能会更好:id、所有者、房间、消息、发送时间
,因此您可以选择按房间
和按发送时间
排序。