DataTable의 집계 함수인 Compute 메서드는 조건에 맞는 행을 조회하여 특정 컬럼을 집계하는 기능을 가진 메서드입니다.
Compute 메서드에서 사용 가능한 집계 유형은 다음과 같습니다.
일반적으로 우리가 알고 있는 합계(SUM), 평균(AVG), 최소(MIN), 최대(MAX), 개수(COUNT)을 지원합니다.
추가적으로 다음 유형도 지원합니다.
- 통계적 표준편차(STDEV)
- 통계적 분산(VAR)
- AVG(자식데이터테이블.컬럼명) : 자식 데이터 테이블 컬럼의 평균
이번 포스팅에서는 일반적으로 사용하는 집계 유형에 대해 정리하였습니다.
Compute 메서드
Compute 메서드는 object를 반환합니다.
public object Compute (string? expression, string? filter);
매개변수
string? expression
- 집계하고자 하는 집계 유형과 컬럼입니다.
string? filter
- DataTable 행을 필터 하기 위한 조건문입니다.
사용방법
아래 그림은 예제로 사용할 DataTable의 구조입니다.
슈퍼마다 과일을 판매하고 과일의 가격과 수량 정보를 가지고 있습니다.
예제로 사용할 DataTable모든 과일의 총수량
Compute 메서드는 object를 반환하므로 Convert.ToInt32 메서드를 사용하여 int형으로 변환하였습니다.
SUM(Count)는 Count 컬럼의 합계이며, 조건이 없으므로 두 번째 매개변수는 빈 값("")으로 입력합니다.
int fruitTotalCount = Convert.ToInt32(dt.Compute("SUM(Count)", ""));
Console.WriteLine("모든 과일의 총 수량 : " + fruitTotalCount);
실행 결과
Lotte의 과일 총수량
Lotte라는 조건이 추가되었으므로 두 번째 매개변수에 Market = 'Lotte'를 작성합니다.
int lotteFruitTotalCount = Convert.ToInt32(dt.Compute("SUM(Count)", "Market = 'Lotte'"));
Console.WriteLine("Lotte의 과일 총 수량 : " + lotteFruitTotalCount);
실행 결과
Orange 평균 가격
평균을 구하기 위해 첫 번째 매개변수에 AVG를 사용하였습니다.
그리고 Orang라는 조건이 존재하므로 두 번째 매개변수에 Fruit = 'Orange'를 작성합니다.
int orangeAverage = Convert.ToInt32(dt.Compute("AVG(Price)", "Fruit = 'Orange'"));
Console.WriteLine("Orange의 평균 가격 : " + orangeAverage);
실행 결과
Homeplus에서 모든 과일을 판매한 금액
아래 코드를 사용할 경우 예외가 발생합니다.
dt.Compute("SUM(Price * Count)", "Market = 'Homeplus'"))
예외 발생
집계 유형의 소괄호에는 한 개의 컬럼만 가능합니다.
이러한 경우에는 아래 2가지 방법을 사용하여 해결할 수 있습니다.
1. Price * Count 값을 가지는 컬럼을 추가한다.
2. 별도의 로직을 구현한다.
저는 MS에서 권장하는 첫 번째 방법을 사용하여 해결하였습니다.
TotalPrice라는 컬럼을 추가합니다.
이때, Expression 속성을 사용하여 TotalPrice의 값은 Prcie * Count의 값으로 설정합니다.
그리고 SUM 집계를 TotalPrice 컬럼으로 설정합니다.
DataColumn col = new DataColumn("TotalPrice", typeof(int));
col.Expression = "Price * Count";
dt.Columns.Add(col);
int homeplusTotalPrice = Convert.ToInt32(dt.Compute("SUM(TotalPrice)", "Market = 'Homeplus'"));
Console.WriteLine("HomePlus의 총 판매 금액 : " + homeplusTotalPrice);
TotalPrice 컬럼에 Price * Count 값이 적용되었습니다.
TotalPrice 컬럼이 추가된 DataTable실행 결과
사용된 예제 코드
DataTable dt = new DataTable();
dt.Columns.Add("Market", typeof(string));
dt.Columns.Add("Fruit", typeof(string));
dt.Columns.Add("Price", typeof(int));
dt.Columns.Add("Count", typeof(int));
dt.Rows.Add("Lotte", "Apple", 2000, 10);
dt.Rows.Add("Lotte", "Banana", 3000, 5);
dt.Rows.Add("Lotte", "Grape", 5000, 20);
dt.Rows.Add("Lotte", "Orange", 1000, 0);
dt.Rows.Add("Homeplus", "Apple", 1500, 50);
dt.Rows.Add("Homeplus", "Banana", 2500, 10);
dt.Rows.Add("Homeplus", "Grape", 6000, 40);
dt.Rows.Add("Homeplus", "Orange", 1500, 5);
dt.Rows.Add("Emart", "Apple", 3000, 25);
dt.Rows.Add("Emart", "Banana", 2000, 5);
dt.Rows.Add("Emart", "Grape", 4000, 30);
dt.Rows.Add("Emart", "Orange", 2000, 15);
dt.Rows.Add("GS", "Apple", 1500, 10);
dt.Rows.Add("GS", "Banana", 3000, 20);
dt.Rows.Add("GS", "Grape", 5000, 0);
dt.Rows.Add("GS", "Orange", 1000, 10);
int fruitTotalCount = Convert.ToInt32(dt.Compute("SUM(Count)", ""));
Console.WriteLine("모든 과일의 총 수량 : " + fruitTotalCount);
Console.WriteLine();
int lotteFruitTotalCount = Convert.ToInt32(dt.Compute("SUM(Count)", "Market = 'Lotte'"));
Console.WriteLine("Lotte의 과일 총 수량 : " + lotteFruitTotalCount);
Console.WriteLine();
int orangeAverage = Convert.ToInt32(dt.Compute("AVG(Price)", "Fruit = 'Orange'"));
Console.WriteLine("Orange의 평균 가격 : " + orangeAverage);
Console.WriteLine();
DataColumn col = new DataColumn("TotalPrice", typeof(int));
col.Expression = "Price * Count";
dt.Columns.Add(col);
int homeplusTotalPrice = Convert.ToInt32(dt.Compute("SUM(TotalPrice)", "Market = 'Homeplus'"));
Console.WriteLine("HomePlus의 총 판매 금액 : " + homeplusTotalPrice);
Console.WriteLine();
|