순서가 오름차순이고 널이 마지막이어야하는 널 열에 의한 LINQ 순서


141

가격별로 제품 목록을 정렬하려고합니다.

결과 집합은 열별로 가격을 기준으로 제품을 나열해야합니다 LowestPrice. 그러나이 열은 널 입력 가능합니다.

목록을 내림차순으로 정렬 할 수 있습니다.

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null

그러나 이것을 오름차순으로 정렬하는 방법을 알 수 없습니다.

// i'd like: 100, 101, 102, null, null

11
orderby p.LowestPrice ?? Int.MaxValue;간단한 방법입니다.
PostMan

3
@PostMan : 예, 간단합니다. 올바른 결과를 얻지 만 OrderByDescending, ThenBy더 명확합니다.
Jason

@Jason, 그래, 나는에 대한 구문을 몰랐고 orderby그것을 찾고 측면 추적을 얻었다 :)
PostMan

답변:


160

두 열을 모두 같은 순서로 배치하십시오.

orderby p.LowestPrice.HasValue descending, p.LowestPrice

그렇지 않으면 각 orderby는 매번 컬렉션을 다시 정렬하는 별도의 작업입니다.

먼저 값을 가진 것들을 순서대로 정렬해야합니다.


21
일반적인 실수로 사람들은 Lamda Syntax와 동일하게 .ThenBy 대신 .OrderBy를 두 번 사용합니다.
DaveShaw

1
이것은 상단에 값이 있고 하단에 null 필드가있는 필드를 주문하는 데 사용했습니다 orderby p.LowestPrice == null, p.LowestPrice ascending .
shaijut

@DaveShaw는 팁을 주셔서 감사합니다 - 특히 주석 하나 - 매우 깔끔 - 사랑이
Demetris Leptos

86

LINQ 쿼리 구문과 LINQ 메서드 호출로 변환되는 방법을 이해하는 데 실제로 도움이됩니다.

그것은 밝혀졌다

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;

컴파일러에 의해

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);

이것은 당신이 원하는 것이 아닙니다. 이 종류에 의해 Product.LowestPrice.HasValue에서 descending위해 다음과 같은 방법으로 전체 컬렉션을-가 정렬 다시 Product.LowestPricedescending순서.

당신이 원하는 것은

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);

쿼리 구문을 사용하여 얻을 수 있습니다.

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;

쿼리 구문에서 메서드 호출로의 변환에 대한 자세한 내용은 언어 사양을 참조하십시오. 진심으로. 읽어.


4
+1 또는 그냥 ... LINQ 쿼리 구문을 쓰지 마십시오 :) 좋은 설명
sehe

18

문자열 값에 대한 해결책은 정말 이상합니다.

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString) 

작동하는 유일한 이유는 첫 번째 표현식 OrderBy()인 정렬 bool값 때문입니다. true/ false. false결과는 먼저 true결과 (널링 가능 항목)를 따르고 널 ThenBy()이 아닌 값을 알파벳순으로 정렬합니다.

따라서 다음과 같이 더 읽기 쉬운 것을 선호합니다.

.OrderBy(f => f.SomeString ?? "z")

SomeStringnull 인 경우 는 대체되어 "z"알파벳순으로 모든 것을 정렬합니다.

참고 :이 "z"같은 z- 값보다 우선하기 때문에 이것은 궁극적 인 해결책이 아닙니다 zebra.

업데이트 9/6/2016-@jornhd 의견에 관해서는, 정말 좋은 솔루션이지만 여전히 약간 복잡하므로 확장 클래스로 래핑하는 것이 좋습니다.

public static class MyExtensions
{
    public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector)
    {
        return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector);
    }
}

그리고 간단하게 사용하십시오 :

var sortedList = list.NullableOrderBy(f => f.SomeString);

2
나는이 더러운 일정하지 않고, 더 읽을 생각 : .OrderBy (=> f.SomeString F = null이 0 : 1!?) .ThenBy (=> f.SomeString F)
jornhd

14

이 상황에서 다른 옵션이 있습니다. 내 목록은 objList이며 주문해야하지만 null은 끝에 있어야합니다. 나의 결정:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));

이것은 null 대신 0과 같은 다른 값으로 결과를 원하는 시나리오에서 작동 할 수 있습니다.
Naresh Ravlani

예. null을 0으로 바꾸십시오.
Gurgen Hovsepyan

이것은 나를 위해 일한 유일한 대답이며 나머지는 목록의 시작 부분에 null을 유지했습니다.
BMills

9

나는 이것에 대한 LINQ 솔루션을 찾으려고했지만 여기의 답변에서 해결할 수 없었습니다.

내 최종 답변은 다음과 같습니다

.OrderByDescending(p => p.LowestPrice.HasValue).ThenBy(p => p.LowestPrice)

7

나의 결정:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)

7

이것은 확장 방법을 사용하고 있기 때문에 내가 생각 해낸 것입니다. 또한 내 항목은 문자열이므로 없습니다 .HasValue.

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)

메모리의 LINQ 2 개체와 함께 작동합니다. EF 또는 DB ORM으로 테스트하지 않았습니다.


0

다음은 keySelector의 하위 속성을 정렬하려는 경우 null을 확인하는 확장 방법입니다.

public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, object> parentKeySelector, Func<T, object> childKeySelector)
{
    return list.OrderBy(v => parentKeySelector(v) != null ? 0 : 1).ThenBy(childKeySelector);
}

그리고 간단하게 사용하십시오 :

var sortedList = list.NullableOrderBy(x => x.someObject, y => y.someObject?.someProperty);

0

다른 방법은 다음과 같습니다.

//Acsending
case "SUP_APPROVED_IND": qry =
                            qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
                                    ThenBy(r => r.SUP_APPROVED_IND);

                            break;
//….
//Descending
case "SUP_APPROVED_IND": qry =
                            qry.OrderBy(r => r.SUP_APPROVED_IND.Trim() == null).
                                    ThenByDescending(r => r.SUP_APPROVED_IND); 

                            break;

SUP_APPROVED_IND is char(1) in Oracle db.

참고 r.SUP_APPROVED_IND.Trim() == null로 처리됩니다trim(SUP_APPROVED_IND) is null 오라클 DB한다.

자세한 내용은 다음을 참조하십시오. 은 엔티티 프레임 워크에서 null 값을 어떻게 쿼리 할 수 ​​있습니까?


0

다른 옵션 (이 시나리오에는 유용했습니다) :

우리는 사용자 테이블을 가지고 있습니다. ADName, LastName, FirstName

  • 사용자는 알파벳순이어야합니다
  • ADName을 기준으로 이름 / 성도없는 계정-사용자 목록 끝에있는 계정
  • ID가 "0"( "선택 없음") 인 더미 사용자는 항상 맨 위에 있어야합니다.

테이블 스키마를 변경하고 일부 정렬 그룹을 정의하는 "SortIndex"열을 추가했습니다. (우리는 5의 간격을 남겨 두었다가 나중에 그룹을 삽입 할 수 있습니다)

ID | ADName |      First Name | LastName | SortIndex
0    No Selection  null         null     | 0
1    AD\jon        Jon          Doe      | 5
3    AD\Support    null         null     | 10     
4    AD\Accounting null         null     | 10
5    AD\ama        Amanda       Whatever | 5

이제 쿼리 방식은 다음과 같습니다.

SELECT * FROM User order by SortIndex, LastName, FirstName, AdName;

메소드 표현식에서 :

db.User.OrderBy(u => u.SortIndex).ThenBy(u => u.LastName).ThenBy(u => u.FirstName).ThenBy(u => u.AdName).ToList();

예상 결과를 산출합니다.

ID | ADName |      First Name | LastName | SortIndex
0    No Selection  null         null     | 0
5    AD\ama        Amanda       Whatever | 5
1    AD\jon        Jon          Doe      | 5
4    AD\Accounting null         null     | 10
3    AD\Support    null         null     | 10     
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.