【问题标题】:Query that fetch messages for a specific user为特定用户获取消息的查询
【发布时间】:2014-05-06 03:15:16
【问题描述】:

我有一个像下面这样的消息表,如何获取特定用户的消息,即获取一个用户最近的一条消息。例如 user1 有带有 的消息user2user3,如何获取 user1user2 之间的最新消息,user1 之间的最新消息user3?

class Message(Base):
    __tablename__ = 'messages'

    id = Column(Integer(), primary_key=True)
    sender_id = Column(Integer(), ForeignKey('users.id'))
    body = Column(Text())
    recipient_id = Column(Integer())
    created_at = Column(DateTime())
    updated_at = Column(DateTime())

我能找出的 SQL 如下,但这还不够。你能帮帮我吗?非常感谢,:)。

session.query(Message).\
filter(or_(Message.user_id==user.id, Message.recipient_id==user.id))

【问题讨论】:

  • 这个问题很难阅读或理解。本质上,您希望 max(id) 按 sender_id 或 recipient_id 分组。 Ir,如果您不能相信 id 会随着“created at”而严格增加,那么您可以进行涉及 select max(id) 的连接,按收件人分组并从您的数据表中发送并与 max(created_at) 连接再次按数据表中的 sender_id 和 recipient_id 分组(显然加入收件人和发件人 ID 以及日期)。但是根据你在这里的情况,很难提供实际的代码。问题不清楚。首先,这不是 SQL....
  • @evanv,谢谢,我认为使用 sql group 是正确的,但我想不通,我已经更新了我的问题。
  • @evanv,对不起,stackoverflow 今天阻止我编辑问题

标签: sql sqlalchemy fetch


【解决方案1】:

试试

from sqlalchemy import desc

session.query(Message).\
filter(or_(Message.user_id==user.id, Message.recipient_id==user.id)).\
order_by(desc(Message.created_at)).\
first()

【讨论】:

  • @dmvianna,对不起,也许我的问题不清楚,你的帮助不正确,:)
【解决方案2】:

下面的代码应该为您提供一个使用created_at 作为最新 的决策列的示例。您可以轻松地将其更改为updated_at
请注意,对于两个用户 (A and B),它将返回 latest 消息:来自A->B 的最新消息和最新的B->A

from datetime import date
from sqlalchemy import create_engine, Column, Text, Integer, DateTime, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.sql import func, and_
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///:memory:', echo=True)
session = sessionmaker(bind=engine)()
Base = declarative_base(engine)

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer(), primary_key=True)
    name = Column(Text())

class Message(Base):
    __tablename__ = 'messages'

    id = Column(Integer(), primary_key=True)
    sender_id = Column(Integer(), ForeignKey('users.id'))
    body = Column(Text())
    recipient_id = Column(Integer(), ForeignKey('users.id'))
    created_at = Column(DateTime())
    updated_at = Column(DateTime())

    sender = relationship(User, backref="messages_sent", foreign_keys=sender_id)
    recipient = relationship(User, backref="messages_recv", foreign_keys=recipient_id)


Base.metadata.create_all()
users = u1, u2, u3 = [
        User(name='user1'),
        User(name='user2'),
        User(name='user3'),
        ]
session.add_all(users)

session.add_all([
    Message(sender=u1, recipient=u2, body="bod12-a", created_at = date(2014, 1, 13)),
    Message(sender=u1, recipient=u2, body="bod12-X", created_at = date(2014, 1, 3)),

    Message(sender=u2, recipient=u3, body="bod23-X", created_at = date(2014, 1, 13)),
    Message(sender=u2, recipient=u3, body="bod23-a", created_at = date(2013, 1, 13)),
    ])
session.flush()

subq = (session
        .query(Message.sender_id, Message.recipient_id,
            func.max(Message.created_at).label("max_created_at"))
        .group_by(Message.sender_id, Message.recipient_id)
        ).subquery("subq")

q = (session
        .query(Message)
        .join(subq, and_(
            Message.sender_id == subq.c.sender_id,
            Message.recipient_id == subq.c.recipient_id,
            Message.created_at == subq.c.max_created_at)
            )
        ).all()
for x in q:
    print(x.sender_id, x.recipient_id, x.body)

【讨论】:

  • 非常感谢,你的关系和我的有点不一样。
猜你喜欢
  • 1970-01-01
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 2020-06-29
相关资源
最近更新 更多