这个需求能用一条 sql 完成吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请要在回答技术问题时复制粘贴 AI 生成的内容
klausgao
V2EX    程序员

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

  •  
  •   klausgao 2017-08-11 09:43:38 +08:00 4592 次点击
    这是一个创建于 2984 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个用户发帖的 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

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

    子查询效率不是很高,
    这个场景 in 和 exists 没区别,
    id 自增,最大的就是最新的一条,用 postdata 不如用主键 id
    babywhisper
        11
    babywhisper  
       2017-08-11 10:28:28 +08:00
    select * from (select * from <table> ORDER BY archiveTime DESC) as tmp GROUP BY tmp.userName
    这样也行把, 但不知道效率如何.
    CRVV
        12
    CRVV  
       2017-08-11 10:32:49 +08:00
    @ayumilove
    跟 Oracle 有什么关系,除了 MySQL 和 SQLite,其它的数据库都支持
    babywhisper
        13
    babywhisper  
       2017-08-11 10:35:56 +08:00
    如果有用**Django ORM**的同学可以参考这篇: https://changchen.me/blog/20170515/ele-interview-solution/
    用 annotate 实现楼主想要的效果 ^_^
    nullcc
        14
    nullcc  
       2017-08-11 10:42:52 +08:00
    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
        15
    anoymoux  
       2017-08-11 10:50:45 +08:00
    加一张表 latest_post(userid,postid)
    ayumilove
        16
    ayumilove  
       2017-08-11 11:11:44 +08:00
    @CRVV 恩,谢谢。 好多年没用过 mysql 了 ,还以为原生 不支持 over(partition by ~)
    quickma
        17
    quickma  
       2017-08-11 11:47:20 +08:00
    加表是一个不错的想法,view 也行呀。
    noNOno
        18
    noNOno  
       2017-08-11 11:55:03 +08:00
    select * from (select *,row_number over (partition by userName order by postdate desc ) as rn from table ) where rn=1

    能用 rownumber 吧
    syncher
        19
    syncher  
       2017-08-11 11:59:51 +08:00 via Android
    又是一个 group
    fxxkgw
        20
    fxxkgw  
       2017-08-11 12:44:17 +08:00
    order by 加 group by
    jeffpan
        21
    jeffpan  
       2017-08-11 14:58:20 +08:00
    SELECT max(login_time) ,user_id ,browser from tb_system_user_login_log group by user_id
    我本地有个类似表,好像这样是可以的。
    Buffer2Disk
        22
    Buffer2Disk  
       2017-08-11 15:02:30 +08:00
    @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
        23
    daemonghost  
       2017-08-11 16:21:14 +08:00 via Android
    先按用户名分组,然后再按日期排序,选取指定个数就行了
    beginor
        24
    beginor  
       2017-08-11 16:39:31 +08:00 via Android
    最佳的方案是 `row_number` + `partition` , 但是 MySQL 不支持
    finull
        25
    finull  
       2017-08-11 21:09:55 +08:00
    select * from table t where not exists ( select * from table where userName = t.userName and postDate > t.postDate );

    不要用聚合什么的
    lenmore
        26
    lenmore  
       2017-08-12 10:34:29 +08:00
    终极做法是:
    当用户发帖时,将最新的 ID 记录到用户表或者单独的一张表。更极端一点把标题时间都冗余了。
    查询时 Join 帖子。
    tsotsi
        27
    tsotsi  
       2017-08-12 15:06:18 +08:00
    ```sql
    select *,if(@lastOne=userName,'',@lastOne:=userName) flag from (select * from table order by userName,postDate desc) a,(select @lastOne :='')b where flag <> ''
    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2782 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 13:18 PVG 21:18 LAX 06:18 JFK 09:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86