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