C#/LINQ

쿼리 식 기본 사항

소나무꼴 2023. 12. 30. 18:04

URL

 

쿼리 식 기본 사항(C#의 LINQ) - C#

쿼리 식과 관련된 개념 소개

learn.microsoft.com

 

 

목차

     

     

    C#의 LINQ 쿼리 식은 특별한 문법을 사용하여 데이터 소스에서 데이터를 쿼리하는 데 사용됩니다. 쿼리 식은 일반적으로 SQL과 비슷한 구문을 제공하여 데이터를 검색, 필터링 및 변환하는 데 편리합니다. 아래는 쿼리 식의 기본 사항에 대한 자세한 설명입니다:

    기본

    from 절:

    from 절은 데이터 소스에서 데이터를 가져오는 역할을 합니다. 데이터 소스의 각 요소를 대상 범위 변수에 할당하여 사용할 수 있도록 합니다.

    from 변수 in 데이터소스

     

    쿼리 변수 및 범위 변수:

    from 절에서 선언된 변수는 쿼리 변수입니다.

    이 변수는 쿼리 식 내에서 사용되며 데이터 소스의 각 요소에 대한 반복을 나타냅니다.
    where, select 절에서 사용되는 변수는 범위 변수로, from 절에서 선언된 쿼리 변수를 참조합니다.

    from num in numbers
    where num % 2 == 0
    select num

    위의 예제에서 num은 쿼리 변수이고, where와 select 절에서 사용됩니다.

     

    여러 from 절:

    여러 데이터 소스에서 데이터를 결합하기 위해 여러 from 절을 사용할 수 있습니다.

    from x in numbers
    from y in numbers
    where x * y > 5
    select new { X = x, Y = y, Product = x * y }


    위의 예제에서 x와 y는 각각의 데이터 소스에 대한 범위 변수입니다.

     

    쿼리 식 종료

    쿼리 식은 group 절 또는 select 절로 끝나야 합니다.

    group 절

    var queryCountryGroups =
        from country in countries
        group country by country.Name[0];

     

    다양한 예제.

    더보기
    public class Country
    {
        public string Name { get; set; }
        public List<City> Cities { get; set; }
        public int Population { get; set; }
    }
    
    public class City
    {
        public string Name { get; set; }
        public int Population { get; set; }
    }
    
    // 국가 및 도시 데이터 생성
    List<Country> countries = new List<Country>
    {
        new Country
        {
            Name = "USA",
            Cities = new List<City>
            {
                new City { Name = "New York", Population = 8000000 },
                new City { Name = "Los Angeles", Population = 4000000 }
                // 추가 도시 정보
            }
        },
        new Country
        {
            Name = "USA",
            Cities = new List<City>
            {
                new City { Name = "Chicago", Population = 8000000 },
                new City { Name = "Houston", Population = 4000000 }
                // 추가 도시 정보
            }
        },
        new Country
        {
            Name = "KOR",
            Cities = new List<City>
            {
                new City { Name = "Seoul ", Population = 8000000 },
                new City { Name = "Daegu", Population = 4000000 }
                // 추가 도시 정보
            }
        },
        // 추가 국가 정보
    };
    
    
    
    // 방법 1 국가코드 앞글자만 Key로 사용
        var queryCountryGroups =
        from country in countries
        group country by country.Name[0];
    
        foreach (var group in queryCountryGroups)
        {
            Debug.Log($"Countries with first letter '{group.Key}':");
    
            foreach (var country in group)
            {
                Debug.Log($"   {country.Name}");
            }
        }
    
        Debug.Log($"");
    
        // 방법2 국가코드를 Key로 사용
        var countries1 = from country in countries
                         group country by country.Name;
    
        foreach (var group in countries1)
        {
            Debug.Log($"Countries with first letter '{group.Key}':");
            foreach (var country in group)
            {
                Debug.Log($"   {country.Name}");
            }
        }
    
        Debug.Log($"");
    
        // 방법3 Key는 국가, Value는 City로
        var queryCountryGroups2 =
            from country in countries
            from city in country.Cities
            group city by country.Name[0];
    
        // LOG queryCountryGroups2
        foreach (var group in queryCountryGroups2)
        {
            Debug.Log($"Countries with first letter '{group.Key}':");
            foreach (var city in group)
            {
                Debug.Log($"   {city.Name}");
            }
        }

     

    select 절

    IEnumerable<Country> sortedQuery =
        from country in countries
        orderby country.Area
        select country;
    var queryNameAndPop =
        from country in countries
        select new
        {
            Name = country.Name,
            Pop = country.Population
        };

     

    into를 사용한 연속

    // percentileQuery is an IEnumerable<IGrouping<int, Country>>
    var percentileQuery =
        from country in countries
        let percentile = (int)country.Population / 10_000_000
        group country by percentile into countryGroup
        where countryGroup.Key >= 20
        orderby countryGroup.Key
        select countryGroup;
    
    // grouping is an IGrouping<int, Country>
    foreach (var grouping in percentileQuery)
    {
        Console.WriteLine(grouping.Key);
        foreach (var country in grouping)
        {
            Console.WriteLine(country.Name + ":" + country.Population);
        }
    }

     

    필터링, 정렬 및 조인

    where 절

    IEnumerable<City> queryCityPop =
        from city in cities
        where city.Population is < 200000 and > 100000
        select city;

    orderby 절

    Area는 오름차순정렬.  Area 이 같다면 Population 내림차순

    IEnumerable<Country> querySortedCountries =
        from country in countries
        orderby country.Area, country.Population descending
        select country;

     

    Area는 오름차순정렬.  Area 이 같다면 Population 오름차순정렬

    IEnumerable<Country> querySortedCountries =
        from country in countries
        orderby country.Area ascending, country.Population ascending
        select country;

     

    join 절

     

    결합하고 새로운걸 만들수 있음.

     

    // 가상의 클래스 정의
        class Category
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    
        class Product
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Category { get; set; }
        }
    
        public void OnClick_join()
        {
            // 가상의 데이터 클래스 정의
            List<Category> categories = new List<Category>
            {
                new Category { Id = 1, Name = "Electronics" },
                new Category { Id = 2, Name = "Clothing" },
                // 추가적인 카테고리들...
            };
    
            List<Product> products = new List<Product>
            {
                new Product { Id = 101, Name = "Laptop", Category = "Electronics" },
                new Product { Id = 102, Name = "Smartphone", Category = "Electronics" },
                new Product { Id = 201, Name = "T-Shirt", Category = "Clothing" },
                // 추가적인 제품들...
            };
    
            // LINQ 쿼리
            var categoryQuery =
                from cat in categories
                join prod in products on cat.Name equals prod.Category
                select new
                {
                    Category = cat.Name,
                    ProductName = prod.Name,
                    createTestID = cat.Id,
                };
    
            // 결과 출력
            foreach (var result in categoryQuery)
            {
                Console.WriteLine($"Category: {result.Category}, Product: {result.ProductName}");
            }
        }

     

    let 절

    string[] names = ["Svetlana Omelchenko", "Claire O'Donnell", "Sven Mortensen", "Cesar Garcia"];
    IEnumerable<string> queryFirstNames =
        from name in names
        let firstName = name.Split(' ')[0]
        select firstName;
    
    foreach (var s in queryFirstNames)
    {
        Console.Write(s + " ");
    }
    
    //Output: Svetlana Claire Sven Cesar

    쿼리 식의 하위 쿼리

    var queryGroupMax =
        from student in students
        group student by student.Year into studentGroup
        select new
        {
            Level = studentGroup.Key,
            HighestScore = (
                from student2 in studentGroup
                select student2.ExamScores.Average()
            ).Max()
        };

     

    쿼리 식의 종류:

    쿼리 식은 쿼리 식 구문과 메서드 구문 두 가지 형식으로 사용할 수 있습니다. 쿼리 식 구문은 SQL과 유사한 구문을 사용하며, 메서드 구문은 메서드 체이닝을 통해 쿼리를 작성하는 방식입니다.

    // 쿼리 식 구문
    var result = from num in numbers
                 where num % 2 == 0
                 select num;
    
    // 메서드 구문
    var result = numbers.Where(num => num % 2 == 0);

     


    두 가지 형식은 기능적으로 동일하며, 개발자는 편한 방식을 선택하여 사용할 수 있습니다.
    쿼리 식은 데이터를 효과적으로 검색하고 조작하는 강력한 도구로, LINQ의 주요 특징 중 하나입니다.

     


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    int[] scores = { 90, 71, 82, 93, 75, 82 };
    
    // 개별 요소를 수정하지 않고 요소의 하위 집합을 검색하여 새 시퀀스를 생성합니다.
    // 쿼리는 다음 예제와 같이 반환된 시퀀스를 다양한 방법으로 정렬하거나 그룹화할 수 있습니다(가정 scores 은 다음과 같습니다. int[]).
    IEnumerable<int> highScoresQuery =
        from score in scores
        where score > 80
        orderby score descending
        select score;
    
    highScoresQuery.ToList().ForEach(score => Debug.Log(score));
    
    // 다음 예제는 int에서 string으로의 프로젝션을 보여 줍니다. highScoresQuery의 새 형식을 참조하세요.
    IEnumerable<string> highScoresQuery2 =
        from score in scores
        where score > 80
        orderby score descending
        select $"The score is {score}";
    
    highScoresQuery2.ToList().ForEach(score => Debug.Log(score));
    
    // 조건과 일치하는 첫 번째 요소 또는 지정된 요소 집합에서 특정 값의 합계. 예를 들어 다음 쿼리는 scores 정수 배열에서 80보다 큰 점수를 반환
    var highScoreCount = (
        from score in scores
        where score > 80
        select score
        ).Count();
    
    Debug.Log(highScoreCount);
    
    // 이전 예제에서는 Enumerable.Count 메서드를 호출하기 전에 쿼리 식 주변에 괄호를 사용했습니다.
    // 새 변수를 사용하여 구체적인 결과를 저장할 수도 있습니다.
    IEnumerable<int> highScoresQuery3 =
        from score in scores
        where score > 80
        select score;
    
    var scoreCount = highScoresQuery3.Count();
    
    Debug.Log(scoreCount);

     

     

    ////////////////////////////////////////

     

    쿼리 변수

    • LINQ에서 쿼리 변수는 쿼리의 결과 대신 쿼리를 저장하는 변수\
    • 하나의 데이터 소스, 하나의 필터링 절, 하나의 순서 지정 절, 변환 없는 원본 요소로 간단한 쿼리 식을 보여 줍니다. select 절은 쿼리를 종료
    // Data source.
    int[] scores = {90, 71, 82, 93, 75, 82};
    
    // Query Expression.
    IEnumerable<int> scoreQuery = //query variable
        from score in scores //required
        where score > 80 // optional
        orderby score descending // optional
        select score; //must end with select or group
    
    // Execute the query to produce the results
    foreach (var testScore in scoreQuery)
    {
        Console.WriteLine(testScore);
    }
    • 위 코드애서 Foreach 할때 실제 데이터가 저장. 지연된다.
    • 두 예제는 쿼리를 사용하여 초기화 하고. 변수를 보여준다. 결과를 저장하기 때문에 쿼리 변수가 아니다
    var highestScore = (
        from score in scores
        select score
    ).Max();
    
    // or split the expression
    IEnumerable<int> scoreQuery =
        from score in scores
        select score;
    
    var highScore = scoreQuery.Max();
    // the following returns the same result
    highScore = scores.Max();
    var largeCitiesList = (
        from country in countries
        from city in country.Cities
        where city.Population > 10000
        select city
    ).ToList();
    
    // or split the expression
    IEnumerable<City> largeCitiesQuery =
        from country in countries
        from city in country.Cities
        where city.Population > 10000
        select city;
    var largeCitiesList2 = largeCitiesQuery.ToList();

     

    'C# > LINQ' 카테고리의 다른 글

    표준 쿼리 연산자 : LINQ를 통한 데이터 변환(C#)  (1) 2024.01.04
    확장명 메서드  (0) 2024.01.03
    C# LINQ 쿼리를 작성하여 데이터 쿼리  (0) 2024.01.01
    LINQ 쿼리 소개(C#)  (0) 2023.12.30