• 请不要在回答技术问题时复制粘贴 AI 生成的内容
klausgao
V2EX  ›  程序员

这个需求能用一条 sql 完成吗?

  •  
  •   klausgao · Aug 11, 2017 · 5450 views
    This topic created in 3371 days ago, the information mentioned may be changed or developed.
    一个用户发帖的 table,能用一条 sql 选出每个用户最新的那条帖子吗?
    例如 table 里的数据:
    id userName post postDate
    1 AA content1 2017-1-1
    2 AA content2 2017-1-2
    3 BB content3 2017-1-3
    4 BB content4 2017-1-4

    sql 选择后,得到结果集:
    id userName post postDate
    2 AA content2 2017-1-2
    4 BB content4 2017-1-4

    想了几天,不得其解。
    Supplement 1  ·  Aug 11, 2017
    没有说清楚,我是用 mysql 的
    27 replies  •  2017-08-12 15:06:18 +08:00
    daimazha
    daimazha
    Aug 11, 2017
    1
    给你个思路:
    select * from x where id in ( select max(id) from x group by name);
    klausgao
    klausgao
    OP
    Aug 11, 2017
    2
    谢谢,我去试试
    @daimazha
    HaoC12
    HaoC12
    Aug 11, 2017
    3
    @daimazha 应该是选出 postdate 最大的吧
    klausgao
    klausgao
    OP
    Aug 11, 2017
    4
    @daimazha 另外多问一句,我记得 in 的效率比较低,是不是这样呢?
    klausgao
    klausgao
    OP
    Aug 11, 2017
    5
    @HaoC12 稍微改一下就好了,@daimazha 给出的是思路。
    LeeSeoung
    LeeSeoung
    Aug 11, 2017❤️1
    6
    select distinct id,userName,post,max(postDate)over(partition by id,userName,post) from xxx
    LeeSeoung
    LeeSeoung
    Aug 11, 2017
    7
    前提 postDate 得是 date 类型的,不是的话自己转换下
    ayumilove
    ayumilove
    Aug 11, 2017
    8
    子查询结果比较大,建议用 exists
    ayumilove
    ayumilove
    Aug 11, 2017
    9
    要是 Oracle 6 楼 的好~
    daimazha
    daimazha
    Aug 11, 2017
    10
    @klausgao #2

    子查询效率不是很高,
    这个场景 in 和 exists 没区别,
    id 自增,最大的就是最新的一条,用 postdata 不如用主键 id
    babywhisper
    babywhisper
    Aug 11, 2017
    11
    select * from (select * from <table> ORDER BY archiveTime DESC) as tmp GROUP BY tmp.userName
    这样也行把, 但不知道效率如何.
    CRVV
    CRVV
    Aug 11, 2017
    12
    @ayumilove
    跟 Oracle 有什么关系,除了 MySQL 和 SQLite,其它的数据库都支持
    babywhisper
    babywhisper
    Aug 11, 2017
    13
    如果有用**Django ORM**的同学可以参考这篇: https://changchen.me/blog/20170515/ele-interview-solution/
    用 annotate 实现楼主想要的效果 ^_^
    nullcc
    nullcc
    Aug 11, 2017
    14
    select A.userName, postDate, post from table A
    inner join
    (select distinct userName, max(postDate) as maxPostDate
    from table
    group by userName) B
    on A.userName = b.userName and A.postDate = B.maxPostDate

    大概是这样
    anoymoux
    anoymoux
    Aug 11, 2017
    15
    加一张表 latest_post(userid,postid)
    ayumilove
    ayumilove
    Aug 11, 2017
    16
    @CRVV 恩,谢谢。 好多年没用过 mysql 了 ,还以为原生 不支持 over(partition by ~)
    quickma
    quickma
    Aug 11, 2017
    17
    加表是一个不错的想法,view 也行呀。
    noNOno
    noNOno
    Aug 11, 2017
    18
    select * from (select *,row_number over (partition by userName order by postdate desc ) as rn from table ) where rn=1

    能用 rownumber 吧
    syncher
    syncher
    Aug 11, 2017 via Android
    19
    又是一个 group
    fxxkgw
    fxxkgw
    Aug 11, 2017
    20
    order by 加 group by
    jeffpan
    jeffpan
    Aug 11, 2017
    21
    SELECT max(login_time) ,user_id ,browser from tb_system_user_login_log group by user_id
    我本地有个类似表,好像这样是可以的。
    Buffer2Disk
    Buffer2Disk
    Aug 11, 2017
    22
    @daimazha 的思路不错,但是如果 id 不是自增的,而是通过 uuid 生成的,这个时候下面这个方法可以解决问题。


    select b.*
    from (
    select
    max(post_date) as post_date,
    user_name
    from article
    group by user_name) as a
    inner join article b ON a.post_date = b.post_date AND a.user_name = b.user_name;

    把用户的名字和发帖时间作为一个联合主键来处理。
    daemonghost
    daemonghost
    Aug 11, 2017 via Android
    23
    先按用户名分组,然后再按日期排序,选取指定个数就行了
    beginor
    beginor
    Aug 11, 2017 via Android
    24
    最佳的方案是 `row_number` + `partition` , 但是 MySQL 不支持
    finull
    finull
    Aug 11, 2017
    25
    select * from table t where not exists ( select * from table where userName = t.userName and postDate > t.postDate );

    不要用聚合什么的
    lenmore
    lenmore
    Aug 12, 2017
    26
    终极做法是:
    当用户发帖时,将最新的 ID 记录到用户表或者单独的一张表。更极端一点把标题时间都冗余了。
    查询时 Join 帖子。
    tsotsi
    tsotsi
    Aug 12, 2017
    27
    ```sql
    select *,if(@lastOne=userName,'',@lastOne:=userName) flag from (select * from table order by userName,postDate desc) a,(select @lastOne :='')b where flag <> ''
    ```
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1734 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 67ms · UTC 23:46 · PVG 07:46 · LAX 15:46 · JFK 18:46
    ♥ Do have faith in what you're doing.