linq C#基于多个条件对行进行比较和分组

a11xaf1n  于 2023-02-14  发布在  C#
关注(0)|答案(3)|浏览(235)

给定一个具有以下行的数据表。

SHOPID   ITEMID   OLD_BATCHNO   NEW_BATCHNO   OLD_QTY   NEW_QTY

SHOP01   ITEM01    BATCH0001                     1        
SHOP01   ITEM01                  BATCH0001                 1
SHOP02   ITEM02    BATCH0002                     2         
SHOP02   ITEM02                  BATCH0002                 3
SHOP03   ITEM03    BATCH0003                     4        
SHOP03   ITEM03                  BATCH0003                 5
SHOP04   ITEM04    BATCH0004                     4
SHOP05   ITEM05                  BATCH0005                 5

预期结果:

SHOPID   ITEMID   OLD_BATCHNO   NEW_BATCHNO   OLD_QTY   NEW_QTY

SHOP02   ITEM02    BATCH0002     BATCH0002       2         3
SHOP03   ITEM03    BATCH0003     BATCH0003       4         5
SHOP04   ITEM04    BATCH0004                     4
SHOP05   ITEM05                  BATCH0005                 5

我想获取满足以下条件的所有行:

    • 匹配的商店ID *
  • 以及
    • 匹配的项目ID *
  • 以及
    • [旧批次编号-新批次编号]不匹配 *
    • 已匹配[旧批次编号-新批次编号],但未匹配[旧数量-新数量]*
6fe3ivhb

6fe3ivhb1#

如果数据表中的行是Item类型,并且这些行是在List<Item> items中收集的,则这应该是一种可能的方法:

var groupedItems = items
    .GroupBy(item => item.SHOPID + item.ITEMID);

var filteredGroupedItems = groupedItems
    .Where(gr =>
        gr
           .Select(item => item.OLD_BATCHNO)
           .Intersect(gr.Select(item => item.NEW_BATCHNO))
           .All(string.IsNullOrEmpty) ||
        gr
           .Select(item => item.OLD_QTY)
           .Intersect(gr.Select(item => item.NEW_QTY))
           .All(qty => !qty.HasValue));

var resultingItems = filteredGroupedItems
    .Select(gr => new Item
        (
            gr.First().SHOPID,
            gr.First().ITEMID,
            gr.FirstOrDefault(item => !string.IsNullOrEmpty(item.OLD_BATCHNO))?.OLD_BATCHNO,
            gr.FirstOrDefault(item => !string.IsNullOrEmpty(item.NEW_BATCHNO))?.NEW_BATCHNO,
            gr.FirstOrDefault(item => item.OLD_QTY.HasValue)?.OLD_QTY,
            gr.FirstOrDefault(item => item.NEW_QTY.HasValue)?.NEW_QTY
        ))
    .ToList();

groupedItems对象满足 * 匹配的SHOPID* 和 * 匹配的ITEMID* 要求。
filteredGroupedItems对象满足以下两个要求中的“之一”要求:

    • [旧批次编号-新批次编号]不匹配 *
    • (匹配[旧批次编号-新批次编号],但)不匹配[旧数量-新数量]*

resultingItems对象是每个筛选分组的“合并”项的集合。
给定示例输入,对应的输出如下所示:

SHOP02   ITEM02   BATCH0002   BATCH0002   2   3
SHOP03   ITEM03   BATCH0003   BATCH0003   4   5
SHOP04   ITEM04   BATCH0004               4    
SHOP05   ITEM05               BATCH0005       5

小提琴here示例。

elcex8rz

elcex8rz2#

你能发布一些你已经尝试过的代码吗?虽然你不太了解如何读取数据,但根据你的linq标记,我猜你可以访问类。
基于对代码的一些假设,我将执行如下操作

var newValues = new List<Value>();
var groupBy = values.GroupBy(x=>$"{x.SHOPID}{x.ITEMID}");
foreach(var group in groupBy){
    var oldRow = group.First(x=> x.NEW_BATCHNO == "");
    var newRow = group.First(x=> x.OLD_BATCHNO == "");
    newValues.Add(new Value(){
        SHOPID = oldRow.SHOPID,
        ITEMID = oldRow.ITEMID,
        OLD_BATCHNO = oldRow.OLD_BATCHNO,
        NEW_BATCHNO = newRow.NEW_BATCHNO,
        OLD_QTY = oldRow.NEW_BATCHNO,
        NEW_QTY = newRow.NEW_BATCHNO,
        };
}
return newValues;
bjp0bcyl

bjp0bcyl3#

试试这个,我试着写一个简单的查询。

var result = datatable
  .Where(d => (d.SHOPID, d.ITEMID) 
    == (datatable.FirstOrDefault(dd => dd.OLD_BATCHNO == dd.NEW_BATCHNO)
        ?? new { SHOPID = default(string), ITEMID = default(string) }))
  .Where(d => d.OLD_BATCHNO == null || d.OLD_BATCHNO != d.NEW_BATCHNO || d.OLD_QTY != d.NEW_QTY);

相关问题