V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
mokeyjay
V2EX  ›  MySQL

请教一个关于 Mysql 按顺序取数据记录的问题,主键非自增

  •  1
     
  •   mokeyjay ·
    mokeyjay · 2017-02-21 20:02:36 +08:00 · 5577 次点击
    这是一个创建于 2819 天前的主题,其中的信息可能已经有所发展或是发生改变。

    部分数据如图所示:

    由于一些历史原因,主键 id 非自增,唯一但不连续

    现在要做的是文章内容页的 下一篇上一篇 按钮

    以上图数据为例,想要达到的效果就是:

    例如当前文章 ID 为137,那么上一篇则为136下一篇则为70。也就是按照表内现有的记录顺序来排

    在不考虑性能开销(访问量很低,且可以做缓存)以及尽可能不修改数据表的前提下,如何取出这上 /下一篇的 ID ?

    谢谢各位

    20 条回复    2017-02-22 07:54:16 +08:00
    psychesworld
        1
    psychesworld  
       2017-02-21 20:07:00 +08:00
    似乎是按时间排序的,你 order by date 就可以了
    mokeyjay
        2
    mokeyjay  
    OP
       2017-02-21 20:12:53 +08:00
    @psychesworld #1 唔……貌似不一定是按照时间来的
    hd7771
        3
    hd7771  
       2017-02-21 20:15:53 +08:00
    你对这个表扫一遍是不是正常顺序?
    batnss
        4
    batnss  
       2017-02-21 20:16:46 +08:00 via Android
    id>xxx order by id asc limit 1
    mokeyjay
        5
    mokeyjay  
    OP
       2017-02-21 20:17:50 +08:00
    @hd7771 #3 什么意思呢?
    hd7771
        6
    hd7771  
       2017-02-21 20:18:26 +08:00
    @mokeyjay 就是你截图里的顺序是怎么得到的
    mokeyjay
        7
    mokeyjay  
    OP
       2017-02-21 20:18:50 +08:00
    @batnss #4 不好意思忘记说了, ID 并不连续,**且并不按照顺序**,目前如图所示的顺序才是正确的。希望能够按照如图顺序取出上 /下一篇的 id
    mokeyjay
        8
    mokeyjay  
    OP
       2017-02-21 20:19:29 +08:00
    @hd7771 #6 就是 select * from xxx limit x 得到的,没有特意去排序
    hd7771
        9
    hd7771  
       2017-02-21 20:23:43 +08:00
    那就 key-value 一下。
    从上往下扫描
    key = 0;
    map1[key] = col.id;
    map2[cao.id] = key;
    key ++;
    key 就是正确的顺序,
    map1[key - 1]就是前一行的 id , map1[key + 1]就是后一行的 id 。
    shiny
        10
    shiny  
       2017-02-21 20:25:14 +08:00
    应该贴 SQL 。看上去像是先按 date 排序,如果 date 相同则按 id ASC

    ORDER BY date DESC, id ASC LIMIT 1
    hd7771
        11
    hd7771  
       2017-02-21 20:25:36 +08:00
    @mokeyjay 你可以把 key-value 存到一个新的表里,你这个表更新,新建的表一起更新就行了。
    mokeyjay
        12
    mokeyjay  
    OP
       2017-02-21 20:34:27 +08:00
    @hd7771 #9
    @shiny #10
    感谢你们
    不过我也不能确定是不是都是按照时间降序&id 升序来排的
    所以最终我决定新建张表存 自增 ID-文章 ID 键值对,这样就能方便的排序了
    (毕竟是二手老项目,还是不要瞎改表结构和数据了)

    再次感谢你们!
    flniu
        13
    flniu  
       2017-02-21 21:11:40 +08:00
    楼主已经有方案了。
    额外补充一句:表不是数组,如果不指定 ORDER BY ,查询结果的顺序是不确定的。所以要么按时间排序,要么增加序号。
    另外自增 ID 可能不连续,所以只能作为序号,但直接用 CurrentID + 1 取下一条可能有问题。
    danielmiao
        14
    danielmiao  
       2017-02-21 22:11:33 +08:00
    方案是有的,就是极其损耗性能:
    使用存储过程游标查询,从头遍历表,直到查到纪录为止。

    最好是只遍历一次,依据数据,建立索引表,链式纪录,指向前一条纪录和后一条纪录 id ,索引表如果数据量不大可以完全缓存在内存里,这样直接命中主键,效率会很高
    akira
        15
    akira  
       2017-02-21 22:26:08 +08:00
    @danielmiao 再加个定时刷新一次记录就好。这种数据量在千万级别以内,都是可以随便开内存处理的
    ETiV
        16
    ETiV  
       2017-02-21 23:04:36 +08:00 via iPhone
    如果 poster 自古以来就是这种命名规范,按它来排序就行了……

    另外根据常理, weight 、权重,也可以是排序依据
    ryd994
        17
    ryd994  
       2017-02-22 02:20:46 +08:00 via Android
    看这个 ID 也不是太稀疏的样子,直接加一看看没有再加一可能反而更快
    测试一下看看
    msg7086
        18
    msg7086  
       2017-02-22 05:24:54 +08:00
    不指定排序条件的,数据库可以自行选择返回数据的顺序。
    MySQL 应该是按照记录的物理存储地址来返回的。
    这就意味着这张数据表如果被导出再导入,可能就不是原来的顺序了。
    will0404
        19
    will0404  
       2017-02-22 07:49:05 +08:00 via iPhone
    不是应该先整理下数据再考虑排序的事吗
    paranoiagu
        20
    paranoiagu  
       2017-02-22 07:54:16 +08:00 via Android
    没有排序字段(规则),怎么确保排序呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1452 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:11 · PVG 01:11 · LAX 09:11 · JFK 12:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.