이번에는 C#에서 DataTable 활용 시 자주 사용되는 중복 값 제거 기능에 대하여 알아보겠습니다.
먼저 모든 Column이 중복일 경우 해당 Row를 제거하는 기능에 대한 코드입니다.
DataTable distinctTable = new DataTable();
distinctTable.DefaultView.ToTable();
해당 기능은 실질적으로 1줄이면 끝나기 때문에 구현이 어렵지는 않습니다.
위의 코드는 모든 컬럼의 데이터가 중복인 Row끼리만 확인하여 제거하는 특징이 있습니다.
그리고 ToTable 함수에 아래 처럼 인자를 넣어주면
distinctTable.DefaultView.ToTable(true, new string[] { "A", "B" });
A, B Column의 데이터만 중복이 되도 중복 제거를 해주지만
결과 테이블에 A, B Column의 데이터만 들어간다는 특징이 있습니다.
물론 상황에 따라서는 유용하게 사용할 수 있지만 전체 테이블의 데이터를 추출하면서 일부 Column만 중복 값일 경우에 해당 Column의 중복 값이 있는 Row만 제거하고 싶은 경우도 있을 것 입니다.
예를 들면 해당 DataTable 변수를 이용하여 통째로 DB에 저장해야 하는데,
Primary Key 제약 조건 때문에 값이 들어가지 않는 경우가 있습니다.
그래서 일부 컬럼의 데이터만 중복일 경우 해당 부분의 데이터만 제거를 해야하는데요.
해당 기능에 대한 코드입니다.
DataTable distinctTable = table.AsEnumerable().GroupBy(r => new { Col1 = r["A"], Col2 = r["B"] }).Select(s => s.OrderBy(r => r["A"]).First()).CopyToDataTable();
코드를 보니 좀 많이 복잡해 보입니다.
먼저 해당 코드에 대한 결과를 예시로 보겠습니다. 먼저 아래와 같은 테이블이 있다고 가정하면
A | B | C |
1 | 2 | A |
1 | 2 | B |
8 | 2 | C |
위의 코드를 적용하고 나면 아래와 같은 결과가 나옵니다.
A | B | C |
1 | 2 | A |
8 | 2 | C |
왜 결과가 이렇게 나오는지 보겠습니다.
먼저 테이블에 LINQ 쿼리를 사용하기 위하여 AsEnumerable()을 쓰고, GroupBy안에 중복 값의 판별 기준을 정할 Column들을 나열합니다.
위의 코드에서는 A, B Column이 중복된 행의 판단 기준입니다.
A Column의 값과 B Column의 값이 같은 Row만 중복으로 인정됩니다.
그 후 Select 함수를 통하여 A Column을 기준으로 First()를 사용하여 오름차순 정렬합니다.
내림차순 정렬은 Last()입니다.
단, 이 정렬은 결과값에 대한 정렬이 아니고 중복 제거전에 정렬 후 중복제거를 진행하기 위한 정렬입니다.
예를 들면 {13, 9, K}, {8, 7, A}, {5, 7, T} 순서로 테이블이 구성되어있을 경우 7 값이 있는 컬럼을 중복 제거한다고 하고 첫 번째 Column을 기준으로 오름차순 정렬했을 때 {5, 7, T}, {8, 7, A}, {13, 9, K} 형태로 정렬 후 맨 앞의 데이터만 제외하고 중복을 제거하여 같은 Column 값을 가진 행들 중에서는 {5, 7, T}만 살아남는 것입니다.
따라서 {13, 9, K}, {5, 7, T} 라는 결과가 출력됩니다.
만약 정렬을 하지 않았거나 내림차순 정렬이었을 경우 {8, 7, A}가 살아남게 되어 {13, 9, K}, {8, 7, A}가 출력됩니다.
그리고 중복 제거 조건을 변경하거나 순서를 변경하는 것도 람다식 조건을 변경해주면 가능하니 입맛대로 사용할 수도 있습니다. 그렇게되면 테이블 구조가 바뀌어도 위의 코드 한 줄로 가능할 것이라고 생각합니다.
이상으로 C#의 DataTable 중복 값 제거 기능에 대하여 알아보았습니다.
C# JSON 형태로 데이터 읽기, 쓰기 (생성 포함) (0) | 2022.07.15 |
---|---|
C# WPF의 3D 관련 기능 간단 정리 (0) | 2022.07.05 |
C# HttpWebRequest의 '이 verb-type으로 content-body를 보낼 수 없습니다.' 예외에 대한 정리 (0) | 2022.06.30 |
C# PC에 잡혀있는 SerialPort 목록 가져오기 (0) | 2021.10.13 |
C# 사용자 지정 특성 작성 (0) | 2021.09.27 |
댓글 영역