V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dingyaguang117
V2EX  ›  Django

问一个蒟蒻的 DjangoORM 问题

  •  
  •   dingyaguang117 ·
    dingyaguang117 · 2015-06-21 14:02:41 +08:00 · 3771 次点击
    这是一个创建于 3432 天前的主题,其中的信息可能已经有所发展或是发生改变。

    要查询每个(其实是一个列表中的)用户的最后一条评论

    Model定义伪代码

    class Comment():
       user_id
       text
       create_time
    

    查询user_id in [1,2,3,4,5]中的的最后一条评论,用Django ORM怎么写? 如果不行的话,SQL怎么写呢

    12 条回复    2015-06-22 08:30:16 +08:00
    yzongyue
        1
    yzongyue  
       2015-06-21 15:41:22 +08:00
    我觉得吧,,,
    Model定义伪代码
    class Comment():
    user
    text
    create_time
    然后,
    clist = []
    for u_id in u_ids:
    c = Comment.objects.filter(user__id__exact=u_id).order_by('create_time')[0]
    clist += c

    命名不规范,大体这意思
    dingyaguang117
        2
    dingyaguang117  
    OP
       2015-06-21 16:27:03 +08:00 via iPhone
    @yzongyue 现在要一条sql出结果。。。
    tini20
        3
    tini20  
       2015-06-21 16:51:23 +08:00
    要想速度好,这个最好用一个专门的表存储
    dalang
        4
    dalang  
       2015-06-21 19:56:06 +08:00   ❤️ 1
    @yzongyue 感觉可以写成
    Comment.objects.filter(user__id__in=u_ids).latest('create_time')
    dingyaguang117
        5
    dingyaguang117  
    OP
       2015-06-21 19:59:43 +08:00
    @dalang 这样是只返回所有里面最新的一条吧?
    yzongyue
        6
    yzongyue  
       2015-06-21 22:10:22 +08:00
    @dalang 还有latest啊,忘了,,题主要求取出每个人的最新评论
    dalang
        7
    dalang  
       2015-06-21 22:17:03 +08:00
    @dingyaguang117 确实误解题意了

    没想到一句 sql 的方法。能想到两条 sql 的,先求出每个 user 对应最新评论的日期:condition_list = Comment.objects.values('user').annotate(create_time=Max('create_time'))

    会得到一个类似[{'create_time': datetime.datetime(2015, 5, 21, 11, 15, 57, tzinfo=<UTC>), 'user': 1L}...] 的 list

    然后用一个 sql 把对应的评论找出来
    query = reduce(lambda q,v: q|(Q(user=v['user')&Q(create_time=v['create_time'])), condition_list, Q())
    Comment.objects.filter(query)
    dingyaguang117
        8
    dingyaguang117  
    OP
       2015-06-21 22:34:56 +08:00 via iPhone
    @dalang 我现在就是这样,第二个用in就可以了
    dingyaguang117
        9
    dingyaguang117  
    OP
       2015-06-21 22:36:24 +08:00 via iPhone
    @dalang django好像对 group by 的控制比较让人费解。。。似乎子查询也必须用raw sql
    aggron
        10
    aggron  
       2015-06-22 08:14:15 +08:00
    希望你用的是postgre,那可以用这样的raw sql:
    select * from comment c where id in ( select id from comment c1 where c2.userId in (1,2,3,4) and c1.useId=c.userId limit 1)
    如果myaql,参考 /t/198719
    aggron
        11
    aggron  
       2015-06-22 08:19:15 +08:00
    typo,应该是c1.userId in
    shengrang
        12
    shengrang  
       2015-06-22 08:30:16 +08:00
    @dalang 正解吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5746 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:00 · PVG 11:00 · LAX 19:00 · JFK 22:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.