[C#] 집계 함수 sum() 및 형식 string 사용이 잘못되었습니다 해결 방법 DataTable string Sum

C#에서 DataTable.Compute 메서드는 string 형식의 컬럼을 직접 합산할 때 "집계 함수 sum() 및 형식 string 사용이 잘못되었습니다"가 발생합니다.

Compute는 숫자 데이터에만 적용되기 때문에, GroupBySelect 구조를 사용할 때, string 형식의 데이터를 숫자로 변환한 후 합산하는 방식이 필요해요.

해당 오류가 발생하는 여러가지 케이스가 있을 텐데요, 이번 예제에서는 GroupBy와 Select 시 발생하는 예제를 다루어 볼게요.

해결 방법

int.TryParsestring 컬럼을 숫자로 변환한 뒤 합산하는 방법을 사용할 수 있습니다. 아래 예제는 DataTablestring 형식의 컬럼을 그룹별로 합산하는 방식으로, 숫자가 아닌 값이 있어도 오류를 방지하고 그룹 합계를 계산할 수 있도록 해보았어요.

예제 코드: DataTable에서 부서별 SALCOMM 합산하기

Oracle의 EMP 테이블을 기반으로 DataTable을 만들고, DEPTNOSAL(급여) 및 COMM(커미션) 컬럼을 그룹 합산합니다. 각 컬럼은 string 형식으로 저장되며, 합산 시 숫자로 변환하여 계산됩니다. *샐러리와 커미션을 스트링으로 하였습니다~

using System;
using System.Data;
using System.Linq;

public class Program
{
    public static void Main()
    {
        // EMP 테이블 구조를 반영한 DataTable 생성
        DataTable dataTable = new DataTable();
        
        dataTable.Columns.Add("EMPNO", typeof(int));      // 직원 번호
        dataTable.Columns.Add("ENAME", typeof(string));   // 직원 이름
        dataTable.Columns.Add("JOB", typeof(string));     // 직무
        dataTable.Columns.Add("MGR", typeof(int));        // 관리자 번호
        dataTable.Columns.Add("HIREDATE", typeof(DateTime)); // 고용 날짜
        dataTable.Columns.Add("SAL", typeof(string));     // 급여 (string 형식으로 가정)
        dataTable.Columns.Add("COMM", typeof(string));    // 커미션 (string 형식으로 가정)
        dataTable.Columns.Add("DEPTNO", typeof(int));     // 부서 번호

        // 예시 데이터 추가
        dataTable.Rows.Add(7369, "SMITH", "CLERK", 7902, DateTime.Parse("1980-12-17"), "800", "0", 20);
        dataTable.Rows.Add(7499, "ALLEN", "SALESMAN", 7698, DateTime.Parse("1981-02-20"), "1600", "300", 30);
        dataTable.Rows.Add(7521, "WARD", "SALESMAN", 7698, DateTime.Parse("1981-02-22"), "1250", "500", 30);
        dataTable.Rows.Add(7566, "JONES", "MANAGER", 7839, DateTime.Parse("1981-04-02"), "2975", "0", 20);
        dataTable.Rows.Add(7698, "BLAKE", "MANAGER", 7839, DateTime.Parse("1981-05-01"), "2850", "0", 30);
        dataTable.Rows.Add(7782, "CLARK", "MANAGER", 7839, DateTime.Parse("1981-06-09"), "2450", "0", 10);
        dataTable.Rows.Add(7788, "SCOTT", "ANALYST", 7566, DateTime.Parse("1982-12-09"), "3000", null, 20);
        dataTable.Rows.Add(7839, "KING", "PRESIDENT", null, DateTime.Parse("1981-11-17"), "5000", null, 10);

        // 부서별 SAL 및 COMM 합산 (DEPTNO 기준)
        var groupedData = dataTable.AsEnumerable()
            .GroupBy(x => x["DEPTNO"])
            .Select(group =>
            {
                DataRow newRow = dataTable.NewRow();
                newRow["ENAME"] = "합계";
                newRow["DEPTNO"] = group.Key;

                foreach (DataColumn column in dataTable.Columns)
                {
                    if (column.ColumnName == "SAL" || column.ColumnName == "COMM")
                    {
                        int sum = group
                            .Select(row => row[column.ColumnName]?.ToString())
                            .Where(value => int.TryParse(value, out _))
                            .Select(int.Parse)
                            .Sum();
                        
                        newRow[column.ColumnName] = sum;
                    }
                }
                return newRow;
            }).CopyToDataTable();

        dataTable.Merge(groupedData);

        // 결과 출력
        foreach (DataRow row in dataTable.Rows)
        {
            Console.WriteLine($"{row["EMPNO"]}, {row["ENAME"]}, {row["JOB"]}, {row["MGR"]}, {row["HIREDATE"]}, {row["SAL"]}, {row["COMM"]}, {row["DEPTNO"]}");
        }
    }
}

출력 결과

7369, SMITH, CLERK, 7902, 1980-12-17 오전 12:00:00, 800, 0, 20
7499, ALLEN, SALESMAN, 7698, 1981-02-20 오전 12:00:00, 1600, 300, 30
7521, WARD, SALESMAN, 7698, 1981-02-22 오전 12:00:00, 1250, 500, 30
7566, JONES, MANAGER, 7839, 1981-04-02 오전 12:00:00, 2975, 0, 20
7698, BLAKE, MANAGER, 7839, 1981-05-01 오전 12:00:00, 2850, 0, 30
7782, CLARK, MANAGER, 7839, 1981-06-09 오전 12:00:00, 2450, 0, 10
7788, SCOTT, ANALYST, 7566, 1982-12-09 오전 12:00:00, 3000, , 20
7839, KING, PRESIDENT, , 1981-11-17 오전 12:00:00, 5000, , 10
, 합계, , , , 6775, 0, 20
, 합계, , , , 5700, 800, 30
, 합계, , , , 7450, 0, 10

코드 설명

  1. DataTable 생성 및 EMP 테이블 구조 설정
    DataTableEMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO 컬럼을 추가하여 EMP 테이블과 유사한 구조를 구성합니다. SALCOMM 컬럼은 string 형식으로 지정하고, 합산 시 숫자로 변환하여 처리합니다.

  2. 샘플 데이터 추가
    예시 데이터를 사용해 DEPTNO별로 그룹화하고, 그룹 내 SALCOMM 컬럼을 합산합니다.

  3. 그룹화 및 합계 계산
    GroupBy를 통해 DEPTNO를 기준으로 데이터를 그룹화하고, 각 그룹의 SALCOMM 컬럼을 int로 변환하여 합산합니다. 변환 불가한 값은 합산에서 제외하여 오류를 방지합니다.

  4. 병합 및 출력
    계산된 합계 행을 기존 DataTable에 병합하여 최종 결과를 생성합니다. 새로운 합계 행에는 각 부서의 SALCOMM 총합이 표시됩니다.

댓글 쓰기
가져가실 때, 출처 표시 부탁드려요! 감사합니다. 💗