Mysql 具有可排列记录的表
Mysql 具有可排列记录的表,mysql,sql,database-design,Mysql,Sql,Database Design,如何创建一个表,使其各行之间按顺序排列并且可以重新排列: 例如: 现在,我想在它们之间插入“Avi”: 不用担心重新排列它们 (1,"john"),(2,"Avi"),(3,"mike") 此表中可以有外键 另一张表(如部门…) 我要的是外表的顺序 要设置,不需要PK 它需要处理大约50K个名称,所以O(n)不是最好的解决方案 插入时可能会触发。我不使用MySQL,但下面是sql server的代码 基本上,在插入时,触发器会增加所有行的appearanceId,这些行的appearance
如何创建一个表,使其各行之间按顺序排列并且可以重新排列:
例如: 现在,我想在它们之间插入“Avi”:
不用担心重新排列它们
(1,"john"),(2,"Avi"),(3,"mike")
- 此表中可以有外键 另一张表(如部门…)
- 我要的是外表的顺序 要设置,不需要PK
- 它需要处理大约50K个名称,所以O(n)不是最好的解决方案
- 插入时可能会触发。我不使用MySQL,但下面是sql server的代码
基本上,在插入时,触发器会增加所有行的appearanceId,这些行的appearanceId等于或大于新的外观id
CREATE Table OrderedTable
(
id int IDENTITY,
name varchar(50),
appearanceOrder int
)
GO
CREATE TRIGGER dbo.MyTrigger
ON dbo.OrderedTable
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE OrderedTable SET
AppearanceOrder = AppearanceOrder + 1
WHERE AppearanceOrder >= (
SELECT TOP 1 AppearanceOrder
FROM inserted )
AND id NOT IN (
SELECT id
FROM inserted )
END
GO
INSERT INTO OrderedTable VALUES ('Alice', 1)
INSERT INTO OrderedTable VALUES ('Bob', 1)
INSERT INTO OrderedTable VALUES ('Charlie', 1)
INSERT INTO OrderedTable VALUES ('David', 1)
这将按预期返回David、Charlie、Bob和Alice
SELECT *
FROM OrderedTable
ORDER BY AppearanceOrder
注意,我还没有完全测试这个实现。一个问题是,如果项目被删除,或者插入内容故意插入到当前范围之外,它会在外观顺序中留下漏洞。如果这些问题很重要,则留给读者作为练习;-) 您可以在插入时使用触发器。我不使用MySQL,但下面是sql server的代码 基本上,在插入时,触发器会增加所有行的appearanceId,这些行的appearanceId等于或大于新的外观id
CREATE Table OrderedTable
(
id int IDENTITY,
name varchar(50),
appearanceOrder int
)
GO
CREATE TRIGGER dbo.MyTrigger
ON dbo.OrderedTable
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE OrderedTable SET
AppearanceOrder = AppearanceOrder + 1
WHERE AppearanceOrder >= (
SELECT TOP 1 AppearanceOrder
FROM inserted )
AND id NOT IN (
SELECT id
FROM inserted )
END
GO
INSERT INTO OrderedTable VALUES ('Alice', 1)
INSERT INTO OrderedTable VALUES ('Bob', 1)
INSERT INTO OrderedTable VALUES ('Charlie', 1)
INSERT INTO OrderedTable VALUES ('David', 1)
这将按预期返回David、Charlie、Bob和Alice
SELECT *
FROM OrderedTable
ORDER BY AppearanceOrder
注意,我还没有完全测试这个实现。一个问题是,如果项目被删除,或者插入内容故意插入到当前范围之外,它会在外观顺序中留下漏洞。如果这些问题很重要,则留给读者作为练习;-) 简单的解决方案是在记录之间有合理的数值间隔。换言之 (10000,“约翰”),(20000,“迈克”) (10000,“约翰”),(15000,“阿维”),(20000,“迈克”) (10000,“约翰”),(12500,“汤姆”),(15000,“阿维”),(20000,“迈克”) 等等
记录之间的间隔应根据数据域确定简单的解决方案是记录之间有合理的数字间隔。换言之 (10000,“约翰”),(20000,“迈克”) (10000,“约翰”),(15000,“阿维”),(20000,“迈克”) (10000,“约翰”),(12500,“汤姆”),(15000,“阿维”),(20000,“迈克”) 等等 记录之间的间隔应根据您的data domain确定如果外观顺序是双精度浮点数,则可以通过一次插入在任意两个相邻名称之间插入任意名称。如果从这样的表开始:
create table test (
person_id integer primary key,
person_name varchar(10) not null,
appearance_order double precision not null unique
);
insert into test values (100, 'John', 11);
insert into test values (23, 'Mike', 12);
在它们之间插入Avi,方法很简单
insert into test values (3, 'Avi', 11.5);
按“外观顺序”列排序
select * from test order by appearance_order
100 John 11
3 Avi 11.5
23 Mike 12
在John和Avi之间插入Eva
insert into test values (31, 'Eva', 11.25);
select * from test order by appearance_order
100 John 11
31 Eva 11.25
3 Avi 11.5
23 Mike 12
您确实需要将标识与排序顺序分开。这意味着使用一列作为id号(并作为外键引用的目标),另一列作为外观顺序。但是,根据您的应用程序,您可能不需要对外观顺序进行唯一约束。如果外观顺序是双精度浮点数,您可以通过一次插入在任意两个相邻名称之间插入任意名称。如果从这样的表开始:
create table test (
person_id integer primary key,
person_name varchar(10) not null,
appearance_order double precision not null unique
);
insert into test values (100, 'John', 11);
insert into test values (23, 'Mike', 12);
在它们之间插入Avi,方法很简单
insert into test values (3, 'Avi', 11.5);
按“外观顺序”列排序
select * from test order by appearance_order
100 John 11
3 Avi 11.5
23 Mike 12
在John和Avi之间插入Eva
insert into test values (31, 'Eva', 11.25);
select * from test order by appearance_order
100 John 11
31 Eva 11.25
3 Avi 11.5
23 Mike 12
您确实需要将标识与排序顺序分开。这意味着使用一列作为id号(并作为外键引用的目标),另一列作为外观顺序。但是,根据您的应用程序,您可能不需要对外观顺序有唯一的限制。为什么要在john和mike之间插入Avi?@Lieven,因为这是一个不言自明的问题,这就是他想要的顺序。@Lieven我明白您的意思。我以前遇到过类似的要求,所以我没有想到这是有问题的。经过深思熟虑,我同意更好地理解这个问题是值得的!在这种情况下,我相信您最好将数据视为一个链接列表,并带有指向下一个(以及上一个,如果需要)值的指针。它会大大加快你的更新速度,而代价是增加一(或两)列。@shevski:我也是?!将
idappearance
重命名为id
,并在表中添加一列,指向下一条记录。为什么要在john和mike之间插入Avi?@Lieven,因为这是一个不言自明的问题,这就是他想要的顺序。@Lieven我明白你的观点。我以前遇到过类似的要求,所以我没有想到这是有问题的。经过深思熟虑,我同意更好地理解这个问题是值得的!在这种情况下,我相信您最好将数据视为一个链接列表,并带有指向下一个(以及上一个,如果需要)值的指针。它会大大加快你的更新速度,而代价是增加一(或两)列。@shevski:我也是?!将idappearance
重命名为id
,并向表中添加一列,该列指向下一条记录。为简单起见,+1。另一个选项是使用非整数类型,如DECIMAL
DECIMAL
更好的方法。可能还应该强制唯一性吗?问题是插入变成了二进制切分的一种形式。在两行之间留出10000的间隙可能使您只能插入14项(2^14=16384)。注意,我假设你总是在两个元素中间插入一个元素,但这是可能的算法finite@shevski这种方法的扩展性很差。由于我已经给出的原因,它很可能无法扩展到100K条记录。@RB我并不是说这个解决方案可以很好地扩展。这取决于你的数据。此解决方案非常简单,仅适用于将容纳有限数量记录的表(例如查找表)。+1为简单起见。另一个选项是使用非整数类型,如DECIMAL