Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL的列表实现_Sql_Algorithm_Sqlite - Fatal编程技术网

SQL的列表实现

SQL的列表实现,sql,algorithm,sqlite,Sql,Algorithm,Sqlite,我需要在SQL数据库之上实现一个列表抽象。此列表抽象需要支持追加、删除和插入操作 我的计划是实现一个键-值表,其中键包含排序/顺序信息,值包含列表值。要将元素附加到顶部,我只需要创建一个键,在上一个顶部之上排序。要插入一个元素,我只需要创建一个键,在插入位置的两个条目之间排序。有了这样的一个方案,我就不需要再平衡表了,因为我在中间插入了一个元素。 一种可能的简单实现是对键使用小数。要在两个元素之间插入一个值,我只需计算两个元素的键的平均值,并将其用作插入值的键。大多数数据库的数字精度有限。为了克

我需要在SQL数据库之上实现一个列表抽象。此列表抽象需要支持追加、删除和插入操作

我的计划是实现一个键-值表,其中键包含排序/顺序信息,值包含列表值。要将元素附加到顶部,我只需要创建一个键,在上一个顶部之上排序。要插入一个元素,我只需要创建一个键,在插入位置的两个条目之间排序。有了这样的一个方案,我就不需要再平衡表了,因为我在中间插入了一个元素。 一种可能的简单实现是对键使用小数。要在两个元素之间插入一个值,我只需计算两个元素的键的平均值,并将其用作插入值的键。大多数数据库的数字精度有限。为了克服这个问题,我们可以将数字转换为字符串,并使用各种任意精度的lib来计算平均值。使用此方案,密钥将增加1位pr insert。请参见下面的示例实现

function between(prev_key:number,next_key:number):number {
  var insert_key = (prev_key + next_key) / 2.0;
  assert(insert_key > prev_key && insert_key < next_key);
  return insert_key;
}
之间的函数(上一个键:数字,下一个键:数字):数字{
var insert_key=(上一个_key+下一个_key)/2.0;
断言(插入\键>上一个\键和插入\键<下一个\键);
返回insert_键;
}
对于插入的每一行,将密钥增加1位不是很容易扩展的。我尝试了不同的密钥方案和“中间”实现。但是,大多数/全部都存在插入时密钥长度快速增长的问题。我的直觉告诉我有一个最佳的策略来解决这个问题,但解决方案却在我的脑海中闪过

注意:在本例中,我使用数字作为键类型,但键可以是字符串或任何其他类型,只要我能够正确生成键和顺序之间的值


有什么想法吗?

通过使用一个值来索引您的值,您将在本质上是数组的基础上实现一个列表

实际使用类似于列表的数据结构会更容易,即每个条目都有指向下一个和上一个节点的指针。在SQL中,指针是外键。在内存列表中,节点的标识将是其地址,这是随机的,因此在SQL中,您只需使用自动递增PK:

CREATE TABLE List (
    ID   INTEGER PRIMARY KEY,
    Prev INTEGER REFERENCES List,
    Next INTEGER REFERENCES List,
    Value
);
要插入或删除,必须调整节点本身及其相邻节点中的
Prev
/
Next

要遍历列表,必须遵循
Next
指针,这需要递归CTE:

WITH RECURSIVE iteration AS (
  SELECT Value, Next
  FROM List
  WHERE ID = 0    -- or Prev IS NULL, or however you identify the first entry

  UNION ALL

  SELECT Value, Next
  FROM List
  JOIN iteration ON List.ID = iteration.Next
)
SELECT Value FROM iteration;

经过一个晚上的睡眠,我想我已经找到了一种方法,为最初的文章中提到的算法问题生成有效的密钥

诀窍是在插入时需要扩展键长度时保留一个值范围。因此,我们“保留”N个数字,而不是像求平均值时那样添加一个数字。在这个保留范围内,我们可以为每一个键大于上一个键的插入计数一。这将为我们提供保留范围内的O(logn)密钥长度。如果我们需要下降,我们将没有空间,需要再次扩张。但第二个技巧是为每次扩展反转保留的范围。因此,在下一个保留范围内,我们从顶部开始倒数

初步测试表明,该结构可以为随机插入和列表和头部中相同位置的多个插入生成非常紧凑的键。但是,我认为如果您使用正确的插入模式“攻击”此结构,则可以使密钥大小增加。因此,递归CTE可能是更安全的方法


如果有人要求,我可以在后面详细说明

嗯,你可以对长度进行一个明显的优化,就是当你取平均值时,试着把它四舍五入,看看它是否仍然有效。即当平均值为1和1.5时,得到1.25。将其四舍五入到1.3,仍然有效。钥匙不长。下一步做1.5和1.3你会得到1.4。或者1和1.3,得到1.15,四舍五入得到可接受的1.2。只有当你在1.2和1.3之间寻找时,你才需要钥匙来实际增加长度。它可能仍然不完美,但至少比每次将密钥增加1位数要好…这将减少问题,但就我所见,并不能解决问题。就列表大小而言,密钥大小的复杂性仍然是O(N),即1M行将生成100k范围内的密钥长度。我正在寻找一些接近O(logn)解决方案的关键尺寸:)谢谢!我没有想过对这个问题应用递归CTE,但你是对的,这将解决我的问题。如果ID上有主键索引,性能应该还可以。我仍然想知道是否有一种方法可以生成键,使我最初的方法适用于大列表。我会让这个线程打开一两天,看看是否有任何有趣的输入。但是考虑你的回答接受!