【问题标题】:The desc order with group by is not working at linqgroup by 的 desc 顺序在 linq 中不起作用
【发布时间】:2019-03-11 09:45:58
【问题描述】:

我正在尝试获取列表的 descending 顺序,然后按 descending 列表进行分组。但我不知道为什么查询不起作用。

List<RentBillRegister> result = _dbContextRent.RentBillRegisters.Where(x => x.Month == month && x.BillId != null).OrderByDescending(c => c.Id)
            .GroupBy(c => c.ClientId)
            .SelectMany(grouping => grouping.Take(1))
            .ToList();

它返回分组的结果不是分组前的列表。分组时我只需要最少的 id。

即使我只是尝试使用此查询查看 desc 结果。

 var result = _dbContextRent.RentBillRegisters.Where(x => x.Month == month && x.BillId != null).OrderByDescending(c => c.Id).ToList();

但它也会返回正在发送的订单列表。任何人都可以解释一下吗?

【问题讨论】:

  • 我无法复制这种行为,您能否在您的程序中查找其他代码。
  • 可能是您的 EF 提供程序/DBMS 中的问题。生成的 SQL 是什么样的?

标签: asp.net entity-framework linq


【解决方案1】:

我无法复制您的简单 Where - OrderByDescending 问题。在我的情况下(Id 是一个 int)序列是正确排序的。

所以我专注于你的第一个问题。

如果在我看来,您希望从您的 RentBillRegisters 序列、每个使用的 ClientId、RentBillRegister 中获得最高的 Id

您首先对所有RentBillRegisters 进行排序,按ID 降序排列;然后你将所有RentBillRegisters 分组到相同的ClientId 组中,并从每个组中获取第一个元素。这应该是该组中 ID 最高的 RentBillRegister

Id | ClientId
01 |    A
02 |    B
03 |    A
04 |    A
05 |    C
06 |    B

// After ordering by descending Id: 
[06 B] [05 C] [04 A] [03 A] [02 B] [01 A]

// After grouping by ClientId and from every group take the first
group B: [06 B] [02 B]          => [06 B]
group C: [05 C]                 => [05 C]
group A: [04 A] [03 A] [01 A]   => [04 A]

如果 RentBillRegister A 和 B 最终会在不同的组中,您为什么要比较它们来订购它们?先对项目进行分组,然后对每个组中的项目进行排序不是更有效吗?

var result = dbContextRent.RentBillRegisters
  .Where(...)

  // make groups of RentBillRegisters that have the same ClientId
  .GroupBy(rentBillRegister => rentBillRegister.ClientId

    // ResultSelector: take the clientId that was selected as key
    // and all rentBillRegisters with this clientId to create a new object
    (clientId, rentBillRegistersWithThisClientId) => 

      // I don't want all RentBillRegisters With This ClientId,
      // I want only the one with the highest Id
      // = the first after sorting by Id in descending order
      // Nota Bene: I don't use the Key (ClientId) anymore
      rentBillRegistersWithThisClientId
        .OrderByDescending(rentBillRegister => rentBillRegister.Id)
        .FirstOrDefault(),
  })

  // now you have from all `RentBillRegisters` with the same clientId the one 
  // with the highest Id. The groups are not ordered yet:
  .OrderByDescending(rentBillRegisterWithHighestId => rentillRegisterWithHighesId.ClientId);

从上面的集合中:

// Make Groups with same ClientId, order and take the first
Group  by  ClientId   | After Ordering       | Take First 
Group with ClientId A | [04 A] [03 A] [01 A] | [04 A]
Group with ClientId B | [06 B] [02 B]        | [06 B]
Group with ClientId C | [05 C]               | [05 C]

// Order the groups by descending Id:
[06 B] [05 C] [04 A]

【讨论】:

  • 非常感谢。实际上,两个 id 都是 long int。我想显示每个客户的所有最新账单,这就是为什么我尝试订购 desc 然后对它们进行排序。现在.OrderByDescending(c =&gt; c.Id) .GroupBy(c =&gt; c.ClientId) .Select(g =&gt; g.OrderByDescending(c =&gt; c.Id).FirstOrDefault()) .ToList(); 对我来说工作正常。
  • 提示:下一个问题给出适当的要求。像:“我想要类似这段代码的东西,但这段代码没有做我想要的”,是不够的。很多时候,它可以帮助我在 LINQ 问题中清楚地写下我想要的内容:从我的输入序列中......给我那些......
【解决方案2】:

所以,我试了一下,编写了一个最简单的示例来尝试一下,由于某种原因,OrderByDesc 不适用于字符串,可能需要提供一个比较器来确定哪个比另一个大。因此,如果您的字段 Id 是一个字符串,那就是问题所在。我尝试了相同的示例,但使用了整数,它按预期工作。 一个简单的解决方案是在 orderBy 中使用 Convert.ToInt32 将 ID 转换为 int。当然,这只有在 ID 只包含数字时才有意义,如果其中有字母,则必须使用另一种技术对它们进行排序。

希望这会有所帮助!

代码示例工作:

        List<string> list = new List<string>() { "5", "2", "1", "10" };

        list.OrderByDescending(item => Convert.ToInt32(item)).ToList().ForEach(itemOrdered => teResult.Text += "  " + itemOrdered.ToString());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 2015-09-23
    相关资源
    最近更新 更多