본문 바로가기
카테고리 없음

grouping

by keisoft 2025. 4. 30.

C#에서 Dapper를 사용하여 IEnumerable<dynamic> 형태로 쿼리 결과를 받은 후, 특정 컬럼들을 제외한 나머지 값이 모두 동일한 행들을 그룹화하고, 그 특정 컬럼들의 값을 쉼표로 연결하는 코드를 작성해 드리겠습니다.

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;

public static IEnumerable<dynamic> GroupAndConcatenateColumns(IEnumerable<dynamic> rows, string[] columnsToConcat)
{
    // 모든 행에서 사용 가능한 속성 이름 추출
    var firstRow = rows.FirstOrDefault();
    if (firstRow == null) return Enumerable.Empty<dynamic>();
    
    var allColumns = ((IDictionary<string, object>)firstRow).Keys.ToArray();
    
    // 그룹화할 컬럼 (연결할 컬럼을 제외한 모든 컬럼)
    var groupColumns = allColumns.Except(columnsToConcat).ToArray();
    
    // 동일한 그룹 컬럼 값을 가진 행들을 그룹화
    var grouped = rows.GroupBy(
        row => new
        {
            // 각 그룹 컬럼에 대한 값을 익명 객체의 속성으로 추가
            GroupKey = string.Join("_", groupColumns.Select(col => ((IDictionary<string, object>)row)[col]?.ToString() ?? "null"))
        },
        // 그룹화된 행을 원본 행 객체로 유지
        row => row
    );
    
    // 결과 생성
    foreach (var group in grouped)
    {
        dynamic result = new ExpandoObject();
        var resultDict = (IDictionary<string, object>)result;
        
        // 첫 번째 행에서 그룹 컬럼 값을 복사
        var firstRowInGroup = group.First();
        var firstRowDict = (IDictionary<string, object>)firstRowInGroup;
        
        foreach (var col in groupColumns)
        {
            resultDict[col] = firstRowDict[col];
        }
        
        // 연결할 컬럼에 대해 모든 값을 쉼표로 연결
        foreach (var concatCol in columnsToConcat)
        {
            var values = group.Select(r => ((IDictionary<string, object>)r)[concatCol]?.ToString() ?? "")
                              .Where(v => !string.IsNullOrEmpty(v))
                              .Distinct();
            resultDict[concatCol] = string.Join(", ", values);
        }
        
        yield return result;
    }
}
```

사용 예시:

```csharp
// 쿼리 결과를 가정
IEnumerable<dynamic> queryResults = ...; // Dapper 쿼리 결과

// 쉼표로 연결할 컬럼 지정
string[] columnsToConcat = new[] { "Category", "Tag" };

// 그룹화 및 연결 수행
var groupedResults = GroupAndConcatenateColumns(queryResults, columnsToConcat);

// 결과 출력
foreach (var row in groupedResults)
{
    // 결과 사용
    Console.WriteLine($"ID: {row.ID}, Name: {row.Name}, Categories: {row.Category}, Tags: {row.Tag}");
}
```

이 코드는 다음과 같은 기능을 제공합니다:

1. 동적으로 지정된 특정 컬럼들을 제외한 나머지 모든 컬럼을 기준으로 그룹화합니다.
2. 각 그룹에 대해 그룹화 컬럼의 값은 첫 번째 행에서 가져옵니다.
3. 연결할 특정 컬럼들의 값을 각 그룹 내에서 중복 제거 후 쉼표로 연결합니다.
4. 결과는 원본과 동일한 구조의 dynamic 객체로 반환됩니다.

필요에 따라 그룹화 로직이나 값 연결 방식을 조정할 수 있습니다.