【问题标题】:How do I find the count of overlapping properties in SQL/LINQ query between two tables?如何在两个表之间的 SQL/LINQ 查询中找到重叠属性的计数?
【发布时间】:2021-06-30 18:21:18
【问题描述】:

假设我有两张桌子。我在这里只展示了必要的内容,但是ShoppingListAShoppingListB 这两个表具有其他属性和对不同对象的 FK,但它们都具有“name”属性。

public class ShoppingListA
{
  public int Id { get; set; }
  public string Name { get; set; }
}

public class ShoppingListB
{
  public int Id { get; set; }
  public string Name { get; set; }
}

我有以下 DTO

public class ShoppingListDto
{
   public int Id { get; set; }
   public string Name { get; set; }
   public int Count {get; set;}
}

此外,我有一个回购方法:

public async Task<List<ShoppingListDto>> GetShoppingLists()
{
       var shoppingListsA = await dbContext.ShoppingListA.Select(shoppingList => new ShoppingListDto
       {
           Id = shoppingList.Id,
           Name = shoppingList.Name,
        }).ToListAsync();

        var shoppingListsB = await dbContext.ShoppingListB.Select(shoppingList => new ShoppingListDto
       {
           Id = shoppingList.Id,
           Name = shoppingList.Name,
        }).ToListAsync()

      var allShoppingLists = shoppingListsA.Concat(shoppingListsB).ToList();
      return allShoppingLists;
}

当我返回 shoppingListsDto 时,我想知道同名在两个表中出现的次数。举个例子。

假设 shoppingListA 是:

[
  { 
    id: 2342352235,
    name: "Weekend Groceries"
  },
 { 
    id: 457457543,
    name: "Dinner party"
  },
]

假设 shoppingListB 是:

[
  { 
    id: 3795794697,
    name: "BBQ stuff"
  },
 { 
    id: q845846q868,
    name: "Dinner party"
  },
]

然后我的 GetShoppingLists 方法将返回:

[
      { 
        id: 3795794697,
        name: "BBQ stuff",
        count: 1,
      },
     { 
        id: q845846q868,
        name: "Dinner party",
        count: 2,
      },
     { 
        id: 2342352235,
        name: "Weekend Groceries",
        count: 1,
      },
     { 
        id: 457457543,
        name: "Dinner party",
        count: 2,
      },
]

【问题讨论】:

  • 这很简单,但没有 ID。

标签: linq linq-to-sql entity-framework-core


【解决方案1】:

要收集重叠属性的计数,您只需对连接表进行分组。

var query =
    from a in dbContext.ShoppingListA
    join b in dbContext.ShoppingListB on a.Name equals b.Name
    group a by a.Name into g
    select ShoppingListDto
    {
        Id = // which ID?
        Name = g.Key,
        Count = g.Count()
    };

【讨论】:

    【解决方案2】:

    当你有一系列相似的项目,并且你想根据一些共同的价值对这些项目进行分组时,考虑使用Enumerable.GroupBy的重载之一

    在您的情况下:您想要创建一组购物清单,其中一组中的每个购物清单都具有相同的属性名称值。

    var shoppingListGroups = shoppinlists.GroupBy(shoppingList => shoppingList.Name,
    
    // parameter resultSelector: for every Name, and all ShopplingLists with this name
    // make one new:
    (name, shoppingListsWithThisName) => new
    {
        Name = name,
        ShoppingListsI = shoppingListsWithThisName.Select(shoppingList => new
        {
            shoppingList.Id,
            Name = shoppingList.Name,
            Count = shoppingListsWithThisName.Count(),
        })
        .ToList(),
    });
    

    简而言之:从您的 ShoppingLists 序列中,创建 ShoppingLists 组,其中每个组中的每个 ShoppingList 都具有相同的属性 ShoppingList.Name 值。从每个组名称和该组中的所有 ShoppingLists(都具有相同的名称),创建一个包含通用名称的对象,以及包含 Id、名称和组中元素数量的对象列表(=所有具有此名称的 ShoppintLists)。

    恕我直言,这没什么用,您已经知道名称,为什么要为组中的所有元素重复此名称,以及为什么要为组中的每个元素重复相同的计数。以下会更有效:

    "Grocery Shopping" has 3 elements with Ids {10, 23, 14}
    "Dinner Party" has 2 elements with Ids {11, 12}
    "BBQ stuff" has 1 element with Id {18}
    

    如果你愿意,查询会容易得多:

    var shoppingListGroups = shoppinlists.GroupBy(shoppingList => shoppingList.Name,
    
    (name, shoppingListsWithThisName) => new
    {
        Name = name,
        Ids = shoppingListsWithThisName.Select(shoppingList => shoppingList.Id).ToList(),
    }
    

    简而言之:创建具有相同属性 ShoppingList.Name 值的 ShoppingList 组。为每个组创建一个对象,其中包含一个名称和一个 ID 列表。 Name 是组中所有 ShoppingLists 的通用名称;该列表包含组中所有 ShoppingLists 的 ID。每个 List 都有一个属性Count,因此您还可以知道每个组中的元素总数。

    结果会更有效率,感觉更自然。

    【讨论】:

      猜你喜欢
      • 2016-05-27
      • 2021-04-21
      • 1970-01-01
      • 2022-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-06
      • 2014-09-29
      相关资源
      最近更新 更多