LINQ 根据计数 >1 的另一列获取列

Posted

技术标签:

【中文标题】LINQ 根据计数 >1 的另一列获取列【英文标题】:LINQ get column based on another column having count >1 【发布时间】:2020-12-22 07:39:00 【问题描述】:

我正在努力通过使用 Entity Framework Core 从数据库中查询 B 列的重复项来获取 A 列的值。示例:

Column A | Column B
--------------------
A        | 1
B        | 1 
C        | 2 
D        | 2 
E        | 3 

我应该得到输出:

A,B,C,D

我打算用它来填充下拉列表。

我试过了:

Options = _context.table.AsEnumerable()
.GroupBy(s => new s.columnA,s.columnB)
.Where(o => o.columnB.Count() > 1)
.Select(o => new SelectListItem

   Value = o.Key.columnA,
   Text = o.Key.columnB
.ToList()

【问题讨论】:

你的问题不清楚。无论您使用 o.columnB.Count() > 1 还是 o.columnB > 1,都无法将 A、B、C、D 作为输出。您应该在 columnB 上对数据进行分组,然后检查组元素的计数。@987654325 @ 这能回答你的问题吗? Linq with group by having count @DragandDrop 不,该解决方案仅显示我正在检查重复项的列(在本例中为 columnB)。我需要显示在 B 列中有重复项的 A 列项目。 正如Karan所说,既然要根据columnB获取重复记录,GroupBy语句应该像这样.GroupBy(s=>s.columnB),然后,您可以使用SelectMany方法找到子项,@ 987654327@ 正确,但是SelectMany() 占用了太多内存。我有一个相当大的数据库。 【参考方案1】:

您只想依靠columnB,然后才应该使用.GroupBy(s => s.columnB)。更新您的WhereSelect,如下所示。

注意需要在其中使用SelectManySelect,因为如果我们使用Select而不是SelectMany,它将返回List<List<SelectListItem>>SelectMany 会将其展平并返回 List<SelectListItem>

Options = _context.table.AsEnumerable()
            .GroupBy(s => s.columnB)
            .Where(o => o.Count() > 1)
            .SelectMany(o => o.Select(x => new SelectListItem
            
               Value = x.columnA,
               Text = x.columnB
            ))
            .ToList();

详细说明 Credits to @Flater from helpful comment. GroupBy 中的 lambda 本质上是“组标识符”。在问题中,每个组由 A B 列的组合唯一性定义。但根据问题的描述,它需要仅基于 B 列组合事物,目标是专门对事物进行分组 无论 A 列包含什么,因此 A 列不应包含在组的标识符中,因为当遇到不同的 A 列值时,查询不应创建新组。

【讨论】:

这是正确的答案,但我认为它可以从为什么需要更改 GroupBy 的小细节中受益:GroupBy 中的 lambda 本质上是“组标识符”。在问题中,每个组由 A B 列的组合唯一性定义。但是 OP 希望仅基于 B 列组合事物,目标是不管 i> 列 A 包含的内容,因此列 A 不应包含在组的标识符中,因为当遇到不同的列 A 值时,查询应该创建一个新组。 @Flater,感谢您的有用评论。我已根据您的评论更新了答案。【参考方案2】:

所以你有 [ColumnA, ColumnB] 的组合,如果你想要 ColumnA 的所有值,其中有多个 ColumnB。

我的建议是将您的 [ColumnA, ColumnB] 转换为“ColumnB”组,其中所有 ColumnA 都具有此 ColumnB。然后只保留具有多个 ColumnA 的组。

所以在你的例子中:

1,值为 A、B 2,值为 C、D 3,值为 E

丢弃第 3 组,因为它只有一个元素,并将结果展平。

我们使用overload of GroupBy that has an elementSelector。 elementSelector 将选择 columnA 作为元素。

var combinationsColumnAColumnB = ...
var result = combinationsColumnB.GroupBy(
     // parameter keySelector: make groups with same ColumnB
     combination => combination.ColumnB,

    // parameter elementselector: put only the ColumnA in each group
    combination => combination.ColumnA)

    // result: groups of columnB with all columnA that belong to this columnB
    // keep only those groups that have more than one element
    .Where(group => group.Skip(1).Any()

    // and flatten the result:
    .SelectMany(group => group);

如果您有以下组合:

A   1
A   2
B   1
C   2

您将获得元素 A 两次。如果您不希望这样,请添加Distinct()

【讨论】:

以上是关于LINQ 根据计数 >1 的另一列获取列的主要内容,如果未能解决你的问题,请参考以下文章

使用同一表中另一列的数据计数更新一列? [关闭]

如何根据R中的另一列获取一列的平均值

根据 Access 中的另一列更新列

如何根据 mySQL 中的另一列选择一列?

SQL Server:选择一列的计数,同时检查另一列中的不同值

基于列值变化的 T-SQL 递增计数器