【问题标题】:Adding missing records to total count (integer) while grouping by in LINQ在 LINQ 中分组时将丢失的记录添加到总数(整数)中
【发布时间】:2017-12-10 19:05:05
【问题描述】:

我有一个奇怪的情况,我有两个集合。一个集合基本上包含我的项目中的所有 ItemID,而另一个集合仅包含有销售的 ItemID(包括销售数据)。

现在我已经确定,Collection #1 中没有出现在 Collection #2 中的 ItemID 的销售额为 0。现在我不知道该怎么办的情况如下:

var items = new List<Collection1>(); // Contains all ItemIDs where ItemID is a plain string

var itemsTransactions = new List<Collection2>(); // contains item id's that have sales.

现在在第三步中,我将通过 itemsTransationCollection 按名为 Username 的属性进行分组,如下所示:

var groupedByUsername = itemTransactions
    .GroupBy( x => x.Username )
    .Select( item => new MyClass
    {
        TotalItems = item
            .Select( x => x.ItemID )
            .Count(), // sub query should be performed here... ?

        SuccessfulItems = item
            .Select( x => x.ItemID )
            .Count()
    } )
    .ToList();

现在的诀窍是成功商品的计算已经正确,因为 itemsTransactions 集合已经只包含实际有销售额的商品 id...

我不确定如何进行我刚才提到的比较,以将丢失的项目包括在此属性TotalItems 的计数中?

所以我的问题是,是否可以在 LINQ 中进行分组时执行子查询以将丢失的项目添加到属性 TotalItems 的计数中?

谁能帮帮我?

@DavidLee 所以输出应该是这样的:

Username  TotalItems(sold + unsold)  Successful items( only ones with sales)
DavidLee    5                                                   2

xyz         4                                                   1
Ronaldo     19                                                  12 

成功的项目不应大于 TotalListings(这在数学上不可能)

对于@Vlad 示例输入和所需输出:

物品集合

ItemID 用户名

1 卖家1 2 卖家2 3 卖家3 4 卖家4 5 卖家5

itemsTransactions 集合:

ItemID     Username     Sales

1          Seller1       2
2          Seller2       4 
3          Seller3       5 
4          Seller4       6 
5          Seller5       7 
5          Seller5       4

itemsTransactions 集合包含未分组的销售数据...这就是我在第三步中对其进行分组的原因...

【问题讨论】:

  • 也许通过参数添加第二组,然后用它做点什么?
  • 您的第一个列表“项目”是否包含任何用于识别用户的内容?还是只有 id?
  • @VladStryapko 是的,它包含第二个集合所做的一切......它们本质上是相同的类型(项目集合也包含 ItemID 和 Username)
  • TotalItems 在所有记录中的编号是否相同?
  • @DavidLee 它不应该是......每个用户名都有由查询确定的唯一数量的 TotalItems =)

标签: c# asp.net asp.net-mvc linq c#-4.0


【解决方案1】:

这是解决方案的最终版本:

   var result = itemsTransactions.GroupBy(_ => _.Name).Select(_ =>
    new
    {
        SuccessfulCount = _.Select(_ => _.ItemId).Distinct().Count(),
        TotalCount = items.Where(item => item.Name == _.Key).Select(it => it.ItemId).Distinct().Count()
    });

【讨论】:

  • 嘿,弗拉德非常感谢您的回复,在某些情况下,第一次查询我得到了更高的成功项目而不是总项目的值(总项目 = 1,成功 = 4 ?)大声笑跨度>
  • 您确定您的初始数据正确吗?您能否提供一个导致此类输出的输入示例?
  • 确定一秒钟我会在我原来的问题中发布:)
  • 我检查了数据,xyz 共有 4 件商品,仅售出 1 件。对我来说似乎没问题。有什么问题?
  • 嘿,弗拉德,老实说,我现在有点困惑...... :D 所以假设我们有这样的情况:ItemID=5 有 60 次销售,ItemID=6 有 40 次销售,并且 ItemID=2有 0 个销售额...输出应该是:TotalListings - 3,成功的列表:2
【解决方案2】:

我会创建两个子查询,然后加入它们。我认为主要问题是使用 itemsTransaction 集合作为起始查询,虽然可以做到,但 IMO 从 items 集合开始更容易。非常冗长,可以缩短,但我发现它更容易理解发生了什么。

var itemsByUser = items
    .GroupBy(x => x.Username)
    .Select(x => new
    {
        Username = x.Key,
        Count = x.Count()
    };

var itemsWithSalesByUser = itemTransactions
    .GroupBy(x => x.Username)
    .Select(x => new
    {
        Username = x.Key,
        Count = x.Count()
    };

var joinedDataQuery =
    from i in itemsByUser 
    join s in itemsWithSalesByUser 
        on i.Username equals s.Username into sj
    from s in sj.DefaultIfEmpty() // left join
    select new MyClass
    {
         Username = i.Username
         TotalItems = i.Count,
         SuccessfulItems = s == null ? 0 : s.Count
    };

// this when it goes to memory so building up the queries 
// in separate variables will not have any performance impacts.
var joinedData = joinedDataQuery.ToList(); 

编辑:将 = 更改为 equals

编辑:考虑可能丢失的成功项目。

【讨论】:

  • 我将 itemsByUser 分组,如果那里有不同数量的记录,可能没有必要,不确定所以我还是这样做了,并没有真正影响任何事情。
猜你喜欢
  • 2013-04-21
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 2016-07-15
  • 2013-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多