【问题标题】:Find the first free id找到第一个空闲的 id
【发布时间】:2019-02-23 14:45:45
【问题描述】:

我的一个小型数据库管理项目(用delphi编写)使用sql查询来查找mysql表的第一个空闲id。

示例:我必须在这样的表中找到第一个空闲 id(孔):

| id   | Col1 |
|------|------|
| 5101 | ABC  |
| 5102 | BCD  |
| 5103 | CDE  |
| 5105 | EFG  | ???? first missing id
| 5106 | GHI  |
| 5108 | ILM  |

代码应该找到第一个空闲的id5104

这是我在 SQL 中的做法(在旧项目中):

SELECT
  MIN((doc.id + 1)) AS nextID
FROM (doc
  LEFT JOIN doc doc1
    ON (((doc.id + 1) = doc1.id)))
WHERE (ISNULL(doc1.id) AND (doc.id > 5000))

现在,我正在用 c# 语言重写,我需要将 sql 语句转换为 LINQ 查询(它使用 Devart dotConnect for mysql Entity Framework)。 从这里开始:

DC db = new DC();
var nums = db.Documentos.OrderBy(x => x.Id);

【问题讨论】:

  • 但是您需要它来添加具有这样值的行吗?还是为了其他目的?
  • 我必须填写空行
  • 如果您使用数据库生成的 ID,只需添加结果直到所需的 ID
  • 这听起来像是一个 X/Y 问题。通常不会重复使用数据库 ID。使这种并发安全几乎是不可能的。您的 Db 是否仅供一次性使用?
  • 您使用的是哪种类型的 LINQ?正如您在答案中看到的那样,人们很容易认为您可以在内存中完成这一切,但我很确定您希望数据库像使用 SQL 语句一样完成繁重的工作。

标签: c# sql linq


【解决方案1】:

来自Can LINQ be used to find gaps in a sorted list?

var strings = new string[] { "7", "13", "8", "12", "10", "11", "14" };
var list = strings.OrderBy(s => int.Parse(s));
var result = Enumerable.Range(list.Min(), list.Count).Except(list).First(); // 9

基本上,对列表进行排序。然后创建一个从最小值一直到最大值的序列号数组 (1,2,3...)。检查列表中的缺失值,并获取第一个。这是第一个缺失的数字。

【讨论】:

    【解决方案2】:

    这会给你的表格中的所有空白

    var nums= (new List<int> (){1,2,3,25,4,5,6,7,8, 12, 15,21,22,23}).AsQueryable();
    
    nums
      .OrderBy(x => x)
      .GroupJoin(nums, n=> n + 1, ni => ni, (o,i)=> new {o, i})
      .Where(t=> !(t.i is IGrouping<int, int>))
      .Dump();
    

    .Net Fiddle

    【讨论】:

    • 请再次检查我的答案。我添加了 .Net Fiddle 链接
    • 确切的错误是什么?你能发布确切的错误吗?而不是编辑我的答案,请编辑您的问题并在那里添加您的尝试
    【解决方案3】:

    另一种方法(类似于您现在使用的方法)。
    假设您有一个整数数组(或其他类型的集合),如下所示:

    var myIDs = new int[] { 5101, 5113, 5102, 5103, 5110, 5104, 5105, 5116, 5106, 5107, 5108, 5112, 5114, 5115 };
    

    如果尚未订购,OrderBy() it:

    myIDs = myIDs.OrderBy(n => n).ToArray();
    

    提取小于(next number) + 1的第一个数字:

    int result = myIDs.Where((n, i) => (i < myIDs.Length - 1) && (n + 1 < myIDs[i + 1])).FirstOrDefault();
    

    如果这个集合中没有一个成员满足条件,取最后一个,加上1

    result = result == default ? myIDs.Last() + 1 : result;
    

    【讨论】:

    • OP 正在使用 dbContext。这种方法意味着他需要将所有内容加载到内存中,然后执行。这不适用于大数据
    • @Simonare 你确定吗?我看不出这是在哪里描述的。我刚刚看到转换为 C# LINQ 表达式
    • 我仔细检查了它,似乎我推测它是因为 SQL。对此感到抱歉:)
    • @Simonare 好吧,可能就像你说的那样。上下文不是那么清楚。也许,看到这些 cmets,OP 会更好地定义它。
    • @Jimi 我听从了你的建议并更好地解释了它(我希望)
    猜你喜欢
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多