【问题标题】:Select a row only if a field from previous row is less from a field in the active row仅当前一行中的字段小于活动行中的字段时才选择一行
【发布时间】:2014-11-25 16:36:40
【问题描述】:

我想知道是否可以创建一个查询,仅当前一行中的字段的值小于实际行中的值时才会选择一行。

如果您查看此屏幕截图:

等于 7 的 ID 不会被选中,因为它后面的行的值小于实际值。所以我想知道是否有一个 LINQ to Entities 命令可以帮助我从选择结果中排除行,例如 id 为 7 的行。

【问题讨论】:

  • 这似乎是一个常用的数据模型。也许如果你解释更高层次的问题,可能会有更好的模型来解决你的问题

标签: c# linq entity-framework tsql linq-to-entities


【解决方案1】:

如果您的 id 保证是连续的,您可以通过 id 将表连接到 id -1 上

var q = from x in test
        join y in test on x.ID equals y.ID - 1
        where y.StopOrder >= y.ID
        select x;

你必须考虑边界条件,你可能想要一个左连接的等价物。

如果您的 id 不连续,您可以执行以下操作:

var q = from x in test
        from y in test 
        where y.ID > x.ID
        group y by x into g
        where g.Min().ID <= g.Min().StopOrder
        select g.Key;

为此,您需要在表类型上定义 IComparable。在我的测试中,我使用了:

struct X: IComparable<X> {
    public int ID;
    public int StopOrder;
    public int CompareTo (X other) {
        return ID.CompareTo(other.ID);
    }
}

这仍然永远不会返回最后一行。

如果您使用的是 SQL2012 或更高版本并且想要下拉到 SQL,您可以使用 lead 函数。这只会扫描一次表(假设 ID 上有一个索引):

with x as (
  select
    t.ID,
    t.StopOrder,
    lead(id, 1) over (order by id) as NextID,
    lead(StopOrder, 1) over (order by id) as NextStopOrder
  from
    test t
) select
  x.ID,
  x.StopOrder
from
  x
where
  x.NextId <= x.NextStopOrder;

另外,如果你想要最后一行,你可以在末尾添加or x.NextID is null

Example SQLFiddle

【讨论】:

  • @Silvermind 如果 id 之间存在差距,它就不起作用。如果是我,我可能会在 sql 中使用row_number(),而不是在这种情况下尝试将其硬塞到 linq 中。
  • @Laurence 你说得对,我非常关注代码,抱歉
【解决方案2】:

由于 SQL 是声明性的,DBMS 可以就如何检索结果做出大量决定,这很可能涉及多线程。

发生这种情况时,无法保证线程完成的顺序,因此,返回结果的顺序 - 即使,如果您定义了主键。 This article 很好地解释了那里发生的事情。

因此,我建议将连续编号按数据库排序,但确保结果从数据库返回后进行排序,然后在 C# 中对排序的结果集进行过滤。

【讨论】:

    【解决方案3】:

    如果表不是太大而无法拉出所有记录,写一个扩展方法来进行过滤可能会更容易(对不起,我不太明白你的意思):

    public static class MyTypeExtensions
    {
        public static IEnumerable<MyType> FilterOnStopOrder(this IEnumerable<MyType> source)
        {
            MyType previous = null;
            foreach (var item in source.OrderBy(s => s.ID))
            {
                // or whatever condition... 
                if (previous != null && previous.StopOrder < item.StopOrder)
                {
                    yield return item;
                }
    
                previous = item;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-18
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多