Tom*_*nal 32 database-design order-by database-agnostic relational-theory
使用数据库时的一个常见需求是按顺序访问记录。例如,如果我有一个博客,我希望能够以任意顺序重新排列我的博客文章。这些条目通常有很多关系,因此关系数据库似乎很有意义。
我见过的常见解决方案是添加一个整数列order:
CREATE TABLE AS your_table (id, title, sort_order)
AS VALUES
(0, 'Lorem ipsum', 3),
(1, 'Dolor sit', 2),
(2, 'Amet, consect', 0),
(3, 'Elit fusce', 1);
Run Code Online (Sandbox Code Playgroud)
然后,我们可以对行进行排序order以使它们按正确的顺序排列。
然而,这似乎很笨拙:
很容易想象这样的情况:
orderorder记录之间有间隙由于多种原因,这些可能很容易发生。
这是 Joomla 等应用程序采用的方法:

你可能会争辩说这里的界面很糟糕,他们应该使用箭头或拖放而不是人类直接编辑数字——你可能是对的。但在幕后,同样的事情正在发生。
有些人建议使用小数来存储订单,这样你就可以使用“2.5”在订单 2 和 3 的记录之间插入一条记录。虽然这有点帮助,但可以说它更混乱,因为你最终可能会得到奇怪的小数(你在哪里停?2.75?2.875?2.8125?)
有没有更好的方法将订单存储在表中?
Mik*_*ll' 18
如果我想将记录 0 移到开头,我必须对每条记录重新排序
不,有一个更简单的方法。
update your_table
set order = -1
where id = 0;
Run Code Online (Sandbox Code Playgroud)
如果我想在中间插入一条新记录,我必须在它之后重新排列每条记录
这是真的,除非您使用支持“介于”值的数据类型。浮点型和数字类型允许您将值更新为 2.5。但是 varchar(n) 也有效。(想想“a”、“b”、“c”;然后想想“ba”、“bb”、“bc”。)
如果我想删除一条记录,我必须在它之后对每条记录重新排序
不,有一个更简单的方法。只需删除该行。其余行仍将正确排序。
很容易想象这样的情况:
两条记录具有相同的顺序
唯一约束可以防止这种情况发生。
记录之间的顺序存在差距
间隙对 dbms 如何对列中的值进行排序没有影响。
有些人建议使用小数来存储订单,这样你就可以使用“2.5”在订单 2 和 3 的记录之间插入一条记录。虽然这有点帮助,但可以说它更混乱,因为你最终可能会得到奇怪的小数(你在哪里停?2.75?2.875?2.8125?)
你不停止,直到你有来。dbms对小数点后有 2、7 或 15 位的值进行排序没有问题。
我认为你真正的问题是,你想看到的排序顺序值作为整数。你可以这样做。
create table your_table (
id int primary key,
title varchar(13),
sort_order float
);
insert into your_table values
(0, 'Lorem ipsum', 2.0),
(1, 'Dolor sit', 1.5),
(2, 'Amet, consect', 0.0),
(3, 'Elit fusce', 1.0);
-- This windowing function will "transform" the floats into sorted integers.
select id, title,
row_number() over (order by sort_order)
from your_table
Run Code Online (Sandbox Code Playgroud)
小智 9
这很简单。你需要有一个“基数洞”结构:
您需要有 2 列:
integerbigint(不是 double)order = round(max_bigint / 2).order = round("order of first record" / 2)order = round("max_bigint - order of last record" / 2)
4) 在中间插入时,设置order = round("order of record before - order of record after" / 2)这个方法有一个非常大的基数。如果您有约束错误,或者您认为基数很小,则可以重建订单列(标准化)。
在标准化(使用这种结构)的最大情况下,您可以在 32 位中拥有“基数洞”。
记住不要使用浮点类型 - order 必须是一个精确的值!
小智 5
一般来说,排序是根据记录中的一些信息、标题、ID 或任何适合特定情况的信息来完成的。
如果您确实需要特殊的排序,那么使用整数列并不像看起来那么糟糕。例如,要为第五名的记录腾出空间,您可以执行以下操作:
update table_1 set place = place + 1 where place > 5。
希望您可以声明该列是unique并且也许有一个程序可以使重新排列“原子”。细节取决于系统,但这是总体思路。