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
      NUMERIC非常理想——我不确定是否有比MySQL中的
      DECIMAL
      更好的方法。可能还应该强制唯一性吗?问题是插入变成了二进制切分的一种形式。在两行之间留出10000的间隙可能使您只能插入14项(2^14=16384)。注意,我假设你总是在两个元素中间插入一个元素,但这是可能的算法finite@shevski这种方法的扩展性很差。由于我已经给出的原因,它很可能无法扩展到100K条记录。@RB我并不是说这个解决方案可以很好地扩展。这取决于你的数据。此解决方案非常简单,仅适用于将容纳有限数量记录的表(例如查找表)。+1为简单起见。另一个选项是使用非整数类型,如
      DECIMAL
      数字是id