두 열의 최소값으로 정렬
사용합니다SQL Server 2008 R2
.
두 열의 최소값으로 테이블을 정렬해야 합니다.
표는 다음과 같습니다.
ID: integer;
Date1: datetime;
Date2: datetime.
나는 내 데이터가 최소 두 날짜까지 정렬되기를 원합니다.
이 테이블을 그런 식으로 정렬하는 가장 간단한 방법은 무엇입니까?
NULL 열이 아닙니다.다음의 ORDER BY 절에 CASE 표현식을 추가해야 합니다.
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN Date1 < Date2 THEN Date1
ELSE Date2
END
NULL 가능 열입니다.Zohar Peled가 코멘트에 썼듯이 열이 무효일 경우 사용할 수 있습니다.ISNULL
(그러나 사용하기에 더 좋습니다.COALESCE
에 ISNULL
것은이기 ANSI SQL standard
에 있는 음과다같다니:)에 있습니다
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN COALESCE(Date1, '1753-01-01') < COALESCE(Date2, '1753-01-01') THEN Date1
ELSE Date2
END
ANSI 표준 날짜 형식에 대해 읽을 수 있습니다.1753-01-01
여기에
을 합니다.CASE
의현에 있는 ORDER BY
:
ORDER BY case when date1 < date2 then date1 else date2 end
편집:
null 값을 고려해야 하는 경우 추가coalesce()
:
ORDER BY case when date1 < date2 then date1 else coalesce(date2,date1) end
설명:
date1 < date2인 경우 date1로 주문합니다. (여기서는 두 날짜가 모두 null이 아닙니다.)예전과 똑같이 작동합니다.
않으면 타기용을 합니다.COALESCE()
null이 경우) null인 경우) null(두null인 경우)로합니다. date2(date2" null인 경우), date1(date2" null인 경우)로 순서를 합니다.
가장 간단한 방법은 다음과 같은 키워드를 사용하는 것입니다.
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY (SELECT MIN(v) FROM (VALUES (Date1), (Date2)) AS value(v))
이 코드는 null 가능한 열에서도 모든 경우에 사용할 수 있습니다.
편집:
솔루션을 통한 솔루션을(를)COALESCE
키워드가 범용이 아닙니다.다음과 같은 중요한 제한 사항이 있습니다.
- 열이 다음과 같은 경우에는 작동하지 않습니다.
Date
앞의 )01/01/1753
) - 중 가 열중하다같은경작않다습니우동지하인 경우에는 하지 않습니다.
NULL
그것은 해석합니다.NULL
합니다.datetime
가치. 하지만 그것이 실제로 사실일까요?그렇지도 않습니다.datetime
,그건 아무것도 아니다. - 그
IF
표현식은 두 개 이상의 열을 사용하면 훨씬 더 복잡해집니다.
질문에 따르면:
이 테이블을 그런 식으로 정렬하는 가장 간단한 방법은 무엇입니까?
가장 짧고 간단한 솔루션은 위에서 설명한 솔루션입니다. 다음과 같은 이유가 있습니다.
- 구현하는 데 많은 코딩이 필요하지 않습니다. 한 줄만 더 추가하면 됩니다.
- 열이 null인지 여부에 대해 신경 쓸 필요가 없습니다.코드를 사용하면 작동합니다.
- 쉼표 뒤에 열을 추가하기만 하면 쿼리의 열 수를 확장할 수 있습니다.
- 이 기능은 다음과 같이 작동합니다.
Date
코드를 수정할 필요가 없습니다.
편집 2:
조하르 펠레드는 다음과 같은 질서 방식을 제안했습니다.
나는 이 규칙에 따라 행을 정렬할 것입니다. 첫째, 둘 다 null일 때, 둘째, date1이 null일 때, 셋째, date2가 null일 때, 넷째, min(date1, date2)
따라서 이 경우 다음과 같은 동일한 접근 방식을 사용하여 해결할 수 있습니다.
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY
CASE WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
WHEN Date1 IS NULL THEN 1
WHEN Date2 IS NULL THEN 2
ELSE 3 END,
(SELECT MIN(v) FROM (VALUES ([Date1]), ([Date2])) AS value(v))
이 코드의 출력은 다음과 같습니다.
그COALESCE
솔루션은 테이블을 이런 식으로 정렬하지 않습니다.그것은 적어도 하나의 셀이 있는 행을 엉망으로 만듭니다.NULL
과 같습니다. 값의 출력은 다음과 같습니다.
이것이 도움이 되고 비평가들을 기다리길 바랍니다.
이것은 다음과 같은 분기를 필요로 하지 않는 대체 솔루션일 수 있습니다.CASE WHEN
이는 다음 공식을 기반으로 합니다.max(a,b)=1/2(a+b+|a−b|)
여기에 기술된 바와 같이우리는 a와 busing의 절대값을 얻습니다.DATEDIFF
참조 날짜 포함('1773-01-01'
).
ORDER BY (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
테스트 데이터
Create Table #DateData(ID int Identity, Name varchar(15),Startdate datetime,EndDate DateTime)
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-19 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-20 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-11 18:48:27','2015-04-22 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-05-09 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-04-17 18:55:38')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-05-12 18:56:29')
쿼리 완료
select *
from #DateData order by (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
사용하지 않으려는 경우Case statement
에 시대에Order By
그렇다면 이것은 또 다른 접근법입니다, 단지 이동하는 것입니다.Case statement
Select
SELECT Id, Date1, Date2 FROM
(SELECT Id, Date1, Date2
,CASE WHEN Date1 < Date2 THEN Date1 ELSE Date2 END as MinDate
FROM YourTable) as T
ORDER BY MinDate
null 가능한 열을 처리하는 방법을 선호합니다.
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY
CASE
WHEN Date1 < Date2 OR Date1 IS NULL THEN Date1
ELSE Date2
END
는 중용사를 합니다.CROSS APPLY
잘 , 공연잘모데요는겠르은요데▁i▁but는ance,▁perform모잘겠르공.CROSS APPLY
종종 제 경험에서 더 나은 성과를 냅니다.
CREATE TABLE #Test (ID INT, Date1 DATETIME, Date2 DATETIME)
INSERT INTO #Test SELECT 1, NULL, '1/1/1';INSERT INTO #Test SELECT 2, NULL, NULL;INSERT INTO #Test SELECT 3, '2/2/2', '3/3/1';INSERT INTO #Test SELECT 4, '3/3/3', '11/1/1'
SELECT t.ID, Date1, Date2, MinDate
FROM #TEST t
CROSS APPLY (SELECT MIN(d) MinDate FROM (VALUES (Date1), (Date2)) AS a(d)) md
ORDER BY MinDate
DROP TABLE #Test
저는 이 작업을 수행하는 방법에서 이 작업이 필요한 이유로 초점을 옮기고 대신 스키마를 변경할 것을 제안합니다.경험의 법칙은 데이터에 접근하기 위해 스턴트를 해야 하는 경우 잘못된 설계 결정이 있다는 것입니다.
이이지 않기 된 모든 인 SQL에 비해 .ORDER BY
.
- 이 작업을 자주 수행해야 하는 경우 두 날짜 중 최소 날짜는 응용 프로그램에 대해 독립적인 물리적 의미가 있어야 합니다.
- 이는 별도의 열(또는 둘 중 하나를 대체하는 열)을 정당화합니다. 트리거에 의해 또는 경우에 따라 열이 둘 중 하나가 아닐 수 있을 정도로 의미가 독립적인 경우 수동으로 유지됩니다.
내 생각에 당신이 두 분야 모두에서 정렬하고 싶을 때.date1
그리고.date2
당신은 두 가지 모두를 가지고 있어야 합니다.ORDER BY
다음과 같은 부품:
SELECT *
FROM aTable
ORDER BY
CASE WHEN date1 < date2 THEN date1
ELSE date2 END,
CASE WHEN date1 < date2 THEN date2
ELSE date1 END
결과는 다음과 같습니다.
date1 | date2
-----------+------------
2015-04-25 | 2015-04-21
2015-04-26 | 2015-04-21
2015-04-25 | 2015-04-22
2015-04-22 | 2015-04-26
다음을 사용하여 검사 결과Null
사용 " 사용":
SELECT *
FROM aTable
ORDER BY
CASE
WHEN date1 IS NULL THEN NULL
WHEN date1 < date2 THEN date1
ELSE date2 END
,CASE
WHEN date2 IS NULL THEN date1
WHEN date1 IS NULL THEN date2
WHEN date1 < date2 THEN date2
ELSE date1 END
결과는 다음과 같습니다.
date1 | date2
-----------+------------
NULL | NULL
NULL | 2015-04-22
2015-04-26 | NULL
2015-04-25 | 2015-04-21
2015-04-26 | 2015-04-21
2015-04-25 | 2015-04-22
다른 방법이 있습니다.필요한 논리에 따라 결과 열을 계산하고 외부 논리에 따라 선택 항목을 열에 따라 정렬할 수 있습니다.이 경우 코드는 다음과 같습니다.
select ID, x.Date1, x.Date2
from
(
select
ID,
Date1,
Date2,
SortColumn = case when Date1 < Date2 then Date1 else Date2 end
from YourTable
) x
order by x.SortColumn
이 솔루션의 이점은 필요한 필터링 쿼리(내부 선택)를 추가할 수 있지만 인덱스는 유용하다는 것입니다.
다음 규칙에 따라 행을 정렬합니다.
- 둘 다 무효일 때
- date1이 null인 경우
- 날짜 2가 null인 경우
- min(날짜1,날짜2)
이를 위해 이 게시물에 따르면 중첩된 사례는 간단하고 효율적입니다(표가 매우 큰 경우는 제외).
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY
CASE
WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
WHEN Date1 IS NULL THEN 1
WHEN Date2 IS NULL THEN 2
ELSE 3 END,
CASE
WHEN Date1 < Date2 THEN Date1
ELSE Date2
END
사용할 수 있습니다.min
에서 기능하는.order by
절:
select *
from [table] d
order by ( select min(q.t) from (
select d.date1 t union select d.date2) q
)
사용할 수도 있습니다.case
의 진술.order by
하지만 당신이 비교한 결과를 알고 있듯이 (>
그리고.<
null인 모든 값(none null 또는 none null)이 아닙니다.true
당신이 설정했더라도ansi_nulls
off
는 그서당이원종하보류위해, 은처야합다니해리당신래기를 처리해야 합니다.null
당신이 있듯이, 피시다아시피.case
의결인경절의 절.when
이라true
그 다음에when
문은 평가되지 않으므로 다음과 같이 말할 수 있습니다.
select * from [table]
order by case
when date1 is null then date2
when date2 is null then date1
when date1<date2 then date1 -- surely date1 and date2 are not null here
else date2
end
시나리오가 다른 경우에도 몇 가지 다른 해결책이 있습니다. 분리된 필드 내에서 여러 열(또는 계산)을 비교한 결과를 평가한 후 절별 주문 내부의 조건을 사용하지 않고 계산된 필드를 기준으로 마지막으로 정렬할 수 있습니다.
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY (SELECT TOP(1) v FROM (VALUES (Date1), (Date2)) AS value(v) ORDER BY v)
@dyatchenko 답변과 매우 유사하지만 NULL 문제는 없습니다.
언급URL : https://stackoverflow.com/questions/29600737/sort-by-minimum-value-of-two-columns
'source' 카테고리의 다른 글
도커 구성 Y를 시작하기 전에 컨테이너 X 대기 (0) | 2023.08.14 |
---|---|
16진수 표현 문자열에서 토이() (0) | 2023.08.09 |
UIAlertAction에 대한 쓰기 처리기 (0) | 2023.08.09 |
jQuery로 입력 필드를 비우는 방법 (0) | 2023.08.09 |
TSLint 자동 수정 경고 (0) | 2023.08.09 |