You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用LINQ实现多表Left Outer Join、分组统计及行值拼接?

Hi there! Let's work through this LINQ problem together. I see you want to retrieve all parents (even those with no children or grandchildren) along with the count of their grandchildren and a comma-separated list of grandchild names. Here's a solution that hits all your requirements:

Complete LINQ Query (Query Expression Style)

var result = from p in Parent
             // Left join Parent to Child to include parents with no children
             join c in Child on p.ParentId equals c.ParentId into childGroup
             from child in childGroup.DefaultIfEmpty()
             // Left join each Child to GrandChild (handle null children with null-propagation)
             join gc in GrandChild on child?.ChildId equals gc.ChildId into grandChildGroup
             from grandChild in grandChildGroup.DefaultIfEmpty()
             // Filter out null grandchildren that come from null children (fixes the "count = 1" bug)
             where grandChild != null || child == null
             // Group by the parent's unique fields to aggregate their grandchildren
             group grandChild by new { p.ParentId, p.ParentName, p.ParentOccupation } into parentGroup
             select new
             {
                 ParentId = parentGroup.Key.ParentId,
                 ParentName = parentGroup.Key.ParentName,
                 ParentOccupation = parentGroup.Key.ParentOccupation,
                 // Count only non-null grandchildren to get 0 for parents with none
                 NumberOfGrandChildren = parentGroup.Count(gc => gc != null),
                 // Join non-null grandchild names into a comma-separated string (empty if none)
                 NamesOfGrandChildren = string.Join(", ", parentGroup.Where(gc => gc != null).Select(gc => gc.GrandChildName))
             };

Key Fixes & Explanations

  1. Handling Nulls Properly:

    • We use child?.ChildId (null-propagation operator) to safely join even when a parent has no children (so child is null).
    • The where clause filters out the dummy null grandchild entries that come from parents with no children. This fixes your earlier issue where parents without grandchildren had a count of 1 instead of 0.
  2. Aggregation Done Right:

    • parentGroup.Count(gc => gc != null) ensures we only count actual grandchildren, giving 0 for parents with none.
    • string.Join first filters out null grandchildren, then joins their names—resulting in an empty string when there are no grandchildren, which matches your expected output.

Alternative: Method Chain Style (EF Core Friendly)

If you're using Entity Framework Core and run into issues with string.Join being unsupported in database queries, pull the data into memory first with AsEnumerable() before processing the string join:

var result = (from p in Parent
             join c in Child on p.ParentId equals c.ParentId into childGroup
             from child in childGroup.DefaultIfEmpty()
             join gc in GrandChild on child?.ChildId equals gc.ChildId into grandChildGroup
             select new
             {
                 p.ParentId,
                 p.ParentName,
                 p.ParentOccupation,
                 // Bring all relevant grandchildren into memory first
                 GrandChildren = grandChildGroup.Where(gc => gc != null)
             })
             .AsEnumerable()
             .Select(x => new
             {
                 x.ParentId,
                 x.ParentName,
                 x.ParentOccupation,
                 NumberOfGrandChildren = x.GrandChildren.Count(),
                 NamesOfGrandChildren = string.Join(", ", x.GrandChildren.Select(gc => gc.GrandChildName))
             });

This version is often more efficient because it lets the database handle the joins and filtering, then processes the string aggregation in memory.

Testing the Result

When you run this query, it will return exactly the output you're expecting:

  • All 5 parents are included
  • Mary has 3 grandchildren with the names "Andrew, Isabelle, Lucas"
  • Anne, Michael, and Andrew have 0 grandchildren and empty name strings
  • Elizabeth has 1 grandchild named "Matthew"

内容的提问来源于stack exchange,提问作者niki b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:18:13