콘텐츠로 건너뛰기
Home » LINQ(링크) group by , join

LINQ(링크) group by , join

  • by
LINQ(링크) group by , join

여러개의 데이터 범위 지정하기

잘 알다시피 LINQ 쿼리식의 from 절은 검색할 데이터의 범위를 지정하는 역할을 합니다.
그럼 만약에 지정한 데이터 범위 내에서 한번 더 데이터 범위를 지정하려면 어떻게 해야할까요?
그때에는 from 절을 중첩해서 사용할수 있습니다.

Student[] StudentList = {
    new Student() {
        name = "A씨",
        score = new int[]{88, 99, 66, 91}
    },
    new Student() {
        name = "B씨",
        score = new int[]{78, 67, 89, 51}
    },
    new Student() {
        name = "C씨",
        score = new int[]{38, 73, 100, 44}
    }
};
var Students = from student in StudentList
from score in student.score
where score > 89
select new {
    Name = student.name,
    failScore = score
};

우선 첫번재 from 에서 학생 리스트로 범위를 지정하고 두번째 from에서 학생 리스트 내에 점수(Score)를 데이터 범위를 지정하였다.
(from 에서 범위를 지정하는 대상은 배열이나 컬렉션이어야 한다. (지난 강의 참고))

마지막으로 추출된 점수 데이터를 가지고 90점 이상인 점수를 걸러서 이름과 점수를 추출한다.
그럼 이제 프로그램을 작성해 보자.

using System;
using System.Linq;
namespace linq_Test {
    class Student {
        public string name {
            get;
            set;
        }
        public int[] score {
            get;
            set;
        }
    }
    class MainApp {
        static void Main(string[] args) {
            Student[] studentList = {
                new Student() {
                    name = "A씨",
                    score = new int[]{88, 99, 66, 91}
                },
                new Student() {
                    name = "B씨",
                    score = new int[]{78, 67, 89, 51}
                },
                new Student() {
                    name = "C씨",
                    score = new int[]{38, 73, 100, 44}
                }
            };
            var Students = from student in StudentList
            from score in student.score
            where score > 89
            select new {
                Name = student.name,
                Score = score
        };
        foreach(var student in Students) {
            Console.WriteLine("Good Score : {0} {1}점", student.Name, student.Score);
        }
    }
}}

group by로 데이터 분류하기

많은 데이터가 중구난방으로 섞여있는 데이터 배열이 있다고 하자.
그리고 나는 이 배열을 특정 기준에 따라 두 그룹으로 나누고 싶다!!

이럴 때에 사용하는 키워드가 group ~ by ~ into 이다.
group A by B into C : A를 B기준에 따라 분류하여 C로 저장한다.

(C 안에는 기준에 따라 두개의 그룹으로 나눠서 저장된다.)

Person[] peopleList = {
    new Person() {
        sex = "여자",
        name = "A씨"
    },
    new Person() {
        sex = "남자",
        name = "B씨"
    },
    new Person() {
        sex = "여자",
        name = "C씨"
    },
    new Person() {
        sex = "남자",
        name = "D씨"
    },
    new Person() {
        sex = "여자",
        name = "E씨"
    }
};
var Group = form person in peopleList
group person by person.sex == "남자" into group
select new {
    sexCheck = group.Key,
    People = group
};

peopleList 에서 person 데이터를 추출해서 남자면 남자 그룹에, 여자면 여자 그룹에 저장한다.
즉, group 안에 남자와 여자 두 그룹으로 나눠서 저장된다.
그리고 group.Key에는 남자 그룹인 경우 true값이, 여자 그럽인 경우 false 값이 저장된다.

최종 Group에 저장되는 데이터는 위 그림과 같다.
이렇게 group by를 사용하면 필요에 따라 원본 데이터를 그룹으로 나워서 사용할수 있다.
그럼 예제를 작성해 보자.

namespace linq_Test {
    class Student {
        public string sex {
            get;
            set;
        }
        public string name {
            get;
            set;
        }
    }
    class MainApp {
        static void Main(string[] args) {
            Person[] peopleList = {
                new Person() {
                    sex = "여자",
                    name = "A씨"
                },
                new Person() {
                    sex = "남자",
                    name = "B씨"
                },
                new Person() {
                    sex = "여자",
                    name = "C씨"
                },
                new Person() {
                    sex = "남자",
                    name = "D씨"
                },
                new Person() {
                    sex = "여자",
                    name = "E씨"
                }
            };
            var Group = form person in peopleList
            group person by person.sex == "남자" into data
            select new {
                sexCheck = group.Key,
                People = data
        };
        foreach(var group in Group) {
            if (group.sexCheck) { // 남자인 경우
                Console.WriteLine("[남자 리스트]");
                foreach(var person in group.People) {
                    Console.WriteLine("이름: {0}", person.name);
                }
            } else {
                Console.WriteLine("[여자 리스트]");
                foreach(var person in group.People) {
                    Console.WriteLine("이름: {0}", person.name);
                }
            }
        }
    }
}}

join – 두 데이터 합치기

서로 다른 두개의 데이터가 있는데, 두 개의 데이터가 서로 통합될수 있는 유사성을 가진다면 굳이 따로 따로 처리하기 보다는 하나의 데이터를 통합하여 처리하는 것이 훨씬 효율적일수 있다.

LINQ는 이를 위해 데이터를 통합하는 기능을 제공하는데, 그 기능을 하는 키워드가 join 이다.
join은 LINQ 쿼리식에서 서로 다른 두 데이터를 합치는 기능을 수행한다.

join에는 내부 조인과 외부 조인이 있으며, 이들을 하나씩 알아보자.

(1) 내부 조인

내부 조인은 두 데이터를 비교해서 특정 조건이 일치하는 경우에만 추출하여 통합한다.
예를 들어 1번 데이터에는 A,B,C,D 학생의 인적사항이 담겨 있고, 2번 데이터에는 B,C,D,E 학생의 성적정보가 담겨 있다면, 학생이 일치하는 조건으로 둘을 내부 조인했을대 B,C,D 학생의 데이터만 추출하여 통합한다.

내부조인을 LINQ의 쿼리식으로 작성하면 다음과 같다.

form a in A
join b in B on a.XXX equals b.YYY // a.XXX 와 b.YYY 가 일치하는 a,b 데이터를 추출
join으로 일치되는 a, b 데이터를 추출한 후에, 무영형식을 만들어서 통합시켜주면 된다.
자세한 것은 예제를 통해 살펴보자.

using System;
using System.Linq;
namespace Linq_Test {
    class Profile {
        public string name {
            get;
            set;
        }
        public int age {
            get;
            set;
        }
    }
    class Score {
        public string name {
            get;
            set;
        }
        public string math {
            get;
            set;
        }
        public string english {
            get;
            set;
        }
    }
    class MainApp {
        Profile [] profileList = {
            new Profile() {
                name = "A씨",
                age = 11
            },
            new Profile() {
                name = "B씨",
                age = 22
            },
            new Profile() {
                name = "C씨",
                age = 33
            },
            new Profile() {
                name = "D씨",
                age = 12
            },
            new Profile() {
                name = "E씨",
                age = 15
            }
        };
        Score[] scoreList = {
            new Score() {
                name = "B씨",
                math = 20,
                english = 70
            },
            new Score() {
                name = "E씨",
                math = 50,
                english = 20
            },
            new Score() {
                name = "F씨",
                math = 50,
                english = 20
            },
            new Score() {
                name = "G씨",
                math = 50,
                english = 20
            },
            new Score() {
                name = "H씨",
                math = 50,
                english = 20
            }
        };
        var Students = from profile in profileList join score in scoreList on profile.name equals score.name select new {
            Name = profile.name,
            Age = profile.age,
            Math = score.math,
            English = score.english
    };
    foreach(var student in Students) {
        Console.WriteLine(student);
    }
}}

위 예제를 보면 profileList 와 scoreList에서 이름이 일치하는 경우에만 데이터를 추출해서 무명형식으로 데이터를 통합하였다.
두 데이터에서 이름이 일치되는 것은 B씨, E씨 둘뿐이기 때문에 최종 통합 데이터는 B씨, E씨 의 데이터가 된다.

(2) 외부조인

외부조인은 기본적으로 내부 조인과 비슷하다.
다만 내부 조인은 조건이 일치하는 데이머만 추출 통합했던 것과 달리, 외부조인은 조건이 일치하지 않더라도, 기준 데이터를 하나도 누락시키지 않고 그대로 추출한 후에, 빈 데이터를 채워서 통합한다.

LINQ 쿼리식 에서 외부조인을 작성하는 방법은 다음과 같다.

from a in A
join b in B on a.XXX equals b.YYY into temp
// a.XXX 와 b.YYY 가 일치하는 a,b 데이터를 추출하여 temp 에 저장한다.
// a 데이터는 하나도 누락되지 않는다.

from b in temp.DefaultlIfEmpty(new a() { empty = “공백” })
//temp에서 비어있는 데이터를 채운 후, 다시 b 데이터로 가져온다.

이렇게 작성한 후에 무명 형식을 만들어서 통합시키면 된다.
다음 예제를 통해 좀더 구체적으로 살펴보자.

Profile[] profileList = {
    new Profile() {
        name = "A씨",
        age = 11
    },
    new Profile() {
        name = "B씨",
        age = 22
    },
    new Profile() {
        name = "C씨",
        age = 33
    },
    new Profile() {
        name = "D씨",
        age = 12
    },
    new Profile() {
        name = "E씨",
        age = 15
    }
};
Score[] scoreList = {
    new Score() {
        name = "B씨",
        math = 20,
        english = 70
    },
    new Score() {
        name = "E씨",
        math = 50,
        english = 20
    },
    new Score() {
        name = "F씨",
        math = 50,
        english = 20
    },
    new Score() {
        name = "G씨",
        math = 50,
        english = 20
    },
    new Score() {
        name = "H씨",
        math = 50,
        english = 20
    }
};
var Students = from profile in profileList
join score in scoreList on profile.name equals score.name into temp
from score in temp.DefaultIfEmpty(new Score() {
    math = 100,
    english = 100
})
select new {
    Name = profile.name,
    Age = profile.age,
    Math = score.Math,
    English = score.english
};
foreach(var student in Students) {
    Console.WriteLine(student);
}

내부 조인을 했을때는 B씨, E씨 데이터만 통합되서 출력되었는데, 외부조인 profileList 의 모든 데이터가 출력됩니다.
DefaultIfEmpty 로 비어있는 데이터를 채워줬기 때문에 통합될수 있는것이다.

댓글 남기기