여러 열의 최대 값 중에서 행당 1 개의 값을 어떻게 반환합니까?
TableName
[Number, Date1, Date2, Date3, Cost]
나는 다음과 같이 돌려 줄 필요가있다.
[Number, Most_Recent_Date, Cost]
질문?
CASE 문을 사용할 수 있습니다.
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date1 AND Date2 >= Date3 THEN Date2
WHEN Date3 >= Date1 AND Date3 >= Date2 THEN Date3
ELSE Date1
END AS MostRecentDate
[Microsoft SQL Server 2008 이상에서는 Sven의 간단한 대답을 아래에서 고려해 볼 수 있습니다.]
다음은 T-SQL 및 SQL Server를 사용하는 Max
기능에 대한 또 다른 멋진 솔루션입니다.
SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]
MySQL을 사용하고 있다면,
SELECT GREATEST(col1, col2 ...) FROM table
UNPIVOT
(1)이 가장 빠르며, (1)보다 훨씬 느리지 만 (2)보다 훨씬 빠른 Simulated Unpivot (3)이 뒤 따르는 3 가지 방법이 있습니다.
CREATE TABLE dates
(
number INT PRIMARY KEY ,
date1 DATETIME ,
date2 DATETIME ,
date3 DATETIME ,
cost INT
)
INSERT INTO dates
VALUES ( 1, '1/1/2008', '2/4/2008', '3/1/2008', 10 )
INSERT INTO dates
VALUES ( 2, '1/2/2008', '2/3/2008', '3/3/2008', 20 )
INSERT INTO dates
VALUES ( 3, '1/3/2008', '2/2/2008', '3/2/2008', 30 )
INSERT INTO dates
VALUES ( 4, '1/4/2008', '2/1/2008', '3/4/2008', 40 )
GO
UNPIVOT
)SELECT number ,
MAX(dDate) maxDate ,
cost
FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,
Date3 ) ) as u
GROUP BY number ,
cost
GO
SELECT number ,
( SELECT MAX(dDate) maxDate
FROM ( SELECT d.date1 AS dDate
UNION
SELECT d.date2
UNION
SELECT d.date3
) a
) MaxDate ,
Cost
FROM dates d
GO
UNPIVOT
);WITH maxD
AS ( SELECT number ,
MAX(CASE rn
WHEN 1 THEN Date1
WHEN 2 THEN date2
ELSE date3
END) AS maxDate
FROM dates a
CROSS JOIN ( SELECT 1 AS rn
UNION
SELECT 2
UNION
SELECT 3
) b
GROUP BY Number
)
SELECT dates.number ,
maxD.maxDate ,
dates.cost
FROM dates
INNER JOIN MaxD ON dates.number = maxD.number
GO
DROP TABLE dates
GO
아래의 두 샘플 중 하나가 작동합니다.
SELECT MAX(date_columns) AS max_date
FROM ( (SELECT date1 AS date_columns
FROM data_table )
UNION
( SELECT date2 AS date_columns
FROM data_table
)
UNION
( SELECT date3 AS date_columns
FROM data_table
)
) AS date_query
두 번째는 lassevk의 lassevk 응답에 대한 추가 기능입니다.
SELECT MAX(MostRecentDate)
FROM ( SELECT CASE WHEN date1 >= date2
AND date1 >= date3 THEN date1
WHEN date2 >= date1
AND date2 >= date3 THEN date2
WHEN date3 >= date1
AND date3 >= date2 THEN date3
ELSE date1
END AS MostRecentDate
FROM data_table
) AS date_query
스칼라 함수는 모든 종류의 성능 문제를 야기하므로 가능하면 논리를 인라인 테이블 값 함수로 래핑하는 것이 좋습니다. 이것은 10 개까지의 날짜 목록에서 최소/최대 날짜를 선택한 일부 사용자 정의 함수를 대체하기 위해 사용했던 함수입니다. 1 백만 행의 데이터 집합에서 테스트했을 때 스칼라 함수는 쿼리를 죽이기 전에 15 분 이상 걸렸으며 인라인 TVF는 결과 테이블을 임시 테이블로 선택하는 것과 동일한 시간 인 1 분이 걸렸습니다. 이 함수를 호출하려면 SELECT 또는 CROSS APPLY의 하위 쿼리에서 함수를 호출합니다.
CREATE FUNCTION dbo.Get_Min_Max_Date
(
@Date1 datetime,
@Date2 datetime,
@Date3 datetime,
@Date4 datetime,
@Date5 datetime,
@Date6 datetime,
@Date7 datetime,
@Date8 datetime,
@Date9 datetime,
@Date10 datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT Max(DateValue) Max_Date,
Min(DateValue) Min_Date
FROM (
VALUES (@Date1),
(@Date2),
(@Date3),
(@Date4),
(@Date5),
(@Date6),
(@Date7),
(@Date8),
(@Date9),
(@Date10)
) AS Dates(DateValue)
)
T-SQL (MSSQL 2008+)
SELECT
(SELECT
MAX(MyMaxName)
FROM ( VALUES
(MAX(Field1)),
(MAX(Field2))
) MyAlias(MyMaxName)
)
FROM MyTable1
DECLARE @TableName TABLE (Number INT, Date1 DATETIME, Date2 DATETIME, Date3 DATETIME, Cost MONEY)
INSERT INTO @TableName
SELECT 1, '20000101', '20010101','20020101',100 UNION ALL
SELECT 2, '20000101', '19900101','19980101',99
SELECT Number,
Cost ,
(SELECT MAX([Date])
FROM (SELECT Date1 AS [Date]
UNION ALL
SELECT Date2
UNION ALL
SELECT Date3
)
D
)
[Most Recent Date]
FROM @TableName
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date3 THEN Date2
ELSE Date3
END AS MostRecentDate
Case 문이 순서대로 평가되므로 평가 단계를 생략하고 작성하는 것이 약간 쉬워집니다.
불행하게도 Lasse의 대답 은 겉보기에는 명백하지만 결정적인 결함이 있습니다. NULL 값을 처리 할 수 없습니다. NULL 값이 하나라도 있으면 Date1이 반환됩니다. 불행히도 그 문제를 해결하려는 시도는 매우 혼란스럽고 4 개 이상의 값으로 확장되지 않습니다.
databyss의 첫 번째 답변 은 좋았습니다. 그러나 대답이 단일 테이블의 더 간단한 3 개의 값 대신 다중 테이블 조인에서 3 개의 값으로 쉽게 추정되는지 여부는 명확하지 않았습니다. 나는 3 열의 최대 값을 얻기 위해 이러한 쿼리를 하위 쿼리로 바꾸는 것을 피하고 싶었습니다. 또한 databyss의 훌륭한 아이디어가 약간 정리 될 수 있다고 확신했습니다.
그래서 더 이상 고민하지 않고 여기에 내 솔루션 (databyss의 아이디어에서 파생 된)입니다.
다중 테이블 조인의 효과를 시뮬레이션하기 위해 상수를 선택하는 교차 조인을 사용합니다. 주목해야 할 중요한 점은 필요한 모든 별칭이 올바르게 수행된다는 것입니다 (항상 그렇지는 않음). 이렇게하면 추가 열을 통해 패턴이 매우 단순하고 확장 가능하게 유지됩니다.
DECLARE @v1 INT ,
@v2 INT ,
@v3 INT
--SET @v1 = 1 --Comment out SET statements to experiment with
--various combinations of NULL values
SET @v2 = 2
SET @v3 = 3
SELECT ( SELECT MAX(Vals)
FROM ( SELECT v1 AS Vals
UNION
SELECT v2
UNION
SELECT v3
) tmp
WHERE Vals IS NOT NULL -- This eliminates NULL warning
) AS MaxVal
FROM ( SELECT @v1 AS v1
) t1
CROSS JOIN ( SELECT @v2 AS v2
) t2
CROSS JOIN ( SELECT @v3 AS v3
) t3
문제 : 엔티티에 주어진 최소 비율 값을 선택하십시오. 요구 사항 : 에이전시 비율은 null 일 수 있습니다.
[MinRateValue] =
CASE
WHEN ISNULL(FitchRating.RatingValue, 100) < = ISNULL(MoodyRating.RatingValue, 99)
AND ISNULL(FitchRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue, 99)
THEN FitchgAgency.RatingAgencyName
WHEN ISNULL(MoodyRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue , 99)
THEN MoodyAgency.RatingAgencyName
ELSE ISNULL(StandardPoorsRating.RatingValue, 'N/A')
END
CROSS APPLY 사용 (2005 년 이상) ....
SELECT MostRecentDate
FROM SourceTable
CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
SQL Server 2012에서는 IIF 를 사용할 수 있습니다.
DECLARE @Date1 DATE='2014-07-03';
DECLARE @Date2 DATE='2014-07-04';
DECLARE @Date3 DATE='2014-07-05';
SELECT IIF(@Date1>@Date2,
IIF(@Date1>@Date3,@Date1,@Date3),
IIF(@Date2>@Date3,@Date2,@Date3)) AS MostRecentDate
SQL Server 2005를 사용하는 경우 UNPIVOT 기능을 사용할 수 있습니다. 다음은 완전한 예입니다.
create table dates
(
number int,
date1 datetime,
date2 datetime,
date3 datetime
)
insert into dates values (1, '1/1/2008', '2/4/2008', '3/1/2008')
insert into dates values (1, '1/2/2008', '2/3/2008', '3/3/2008')
insert into dates values (1, '1/3/2008', '2/2/2008', '3/2/2008')
insert into dates values (1, '1/4/2008', '2/1/2008', '3/4/2008')
select max(dateMaxes)
from (
select
(select max(date1) from dates) date1max,
(select max(date2) from dates) date2max,
(select max(date3) from dates) date3max
) myTable
unpivot (dateMaxes For fieldName In (date1max, date2max, date3max)) as tblPivot
drop table dates
UNPIVOT
을 사용해보십시오 :
SELECT MAX(MaxDt) MaxDt
FROM tbl
UNPIVOT
(MaxDt FOR E IN
(Date1, Date2, Date3)
)AS unpvt;
나는 사례 기반으로 솔루션을 선호하는데, 내 가정은 교차 적용, 값 (), 사용자 정의 함수 등과 같은 다른 가능한 솔루션에 비해 가능한 성능 저하에 최소한의 영향을 미쳐야한다는 것입니다.
다음은 대부분의 가능한 테스트 케이스에서 null 값을 처리하는 버전입니다.
SELECT
CASE
WHEN Date1 > coalesce(Date2,'0001-01-01') AND Date1 > coalesce(Date3,'0001-01-01') THEN Date1
WHEN Date2 > coalesce(Date3,'0001-01-01') THEN Date2
ELSE Date3
END AS MostRecentDate
, *
from
(values
( 1, cast('2001-01-01' as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 2, cast('2001-01-01' as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 3, cast('2002-01-01' as Date), cast('2001-01-01' as Date), cast('2003-01-01' as Date))
,( 4, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast('2001-01-01' as Date))
,( 5, cast('2003-01-01' as Date), cast('2001-01-01' as Date), cast('2002-01-01' as Date))
,( 6, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast('2001-01-01' as Date))
,( 11, cast(NULL as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 12, cast(NULL as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 13, cast('2003-01-01' as Date), cast(NULL as Date), cast('2002-01-01' as Date))
,( 14, cast('2002-01-01' as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 15, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast(NULL as Date))
,( 16, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 21, cast('2003-01-01' as Date), cast(NULL as Date), cast(NULL as Date))
,( 22, cast(NULL as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 23, cast(NULL as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 31, cast(NULL as Date), cast(NULL as Date), cast(NULL as Date))
) as demoValues(id, Date1,Date2,Date3)
order by id
;
결과는 다음과 같습니다.
MostRecent id Date1 Date2 Date3
2003-01-01 1 2001-01-01 2002-01-01 2003-01-01
2003-01-01 2 2001-01-01 2003-01-01 2002-01-01
2003-01-01 3 2002-01-01 2001-01-01 2002-01-01
2003-01-01 4 2002-01-01 2003-01-01 2001-01-01
2003-01-01 5 2003-01-01 2001-01-01 2002-01-01
2003-01-01 6 2003-01-01 2002-01-01 2001-01-01
2003-01-01 11 NULL 2002-01-01 2003-01-01
2003-01-01 12 NULL 2003-01-01 2002-01-01
2003-01-01 13 2003-01-01 NULL 2002-01-01
2003-01-01 14 2002-01-01 NULL 2003-01-01
2003-01-01 15 2003-01-01 2002-01-01 NULL
2003-01-01 16 2002-01-01 2003-01-01 NULL
2003-01-01 21 2003-01-01 NULL NULL
2003-01-01 22 NULL 2003-01-01 NULL
2003-01-01 23 NULL NULL 2003-01-01
NULL 31 NULL NULL NULL
가장 큰 ID를 얻으려면 TblItem이라는 테이블이 있습니다. 다음 코드를 사용합니다.
select MAX(Id) from TblItem
사용하는 또 다른 방법 사례
SELECT CASE true
WHEN max(row1) >= max(row2) THEN CASE true WHEN max(row1) >= max(row3) THEN max(row1) ELSE max(row3) end ELSE
CASE true WHEN max(row2) >= max(row3) THEN max(row2) ELSE max(row3) END END
FROM yourTable
ScottPletcher 의 솔루션을 기반으로 http://www.experts-exchange.com/Microsoft/Development /MS-SQL-Server/Q_24204894.html UNION ALL을 사용하여 최대 13 개의 Date 값을 찾을 수있는 함수 집합 (예 : GetMaxOfDates3, GetMaxOfDates13)을 만들었습니다. 참조 동일한 행에서 값의 최대 값을 얻는 T-SQL 함수 그러나 이러한 함수를 작성할 때 UNPIVOT 솔루션을 고려하지 않았습니다.
날짜를 전달하는 함수를 작성한 다음 아래 함수를 select 문에 추가 할 수 있습니다. 번호, dbo.fxMost_Recent_Date (날짜 1, 날짜 2, 날짜 3), 비용 선택
create FUNCTION fxMost_Recent_Date
(@ Date1 smalldatetime, @ Date2 smalldatetime, @ Date3 smalldatetime) 리턴 값 smalldatetime AS BEGIN DECLARE @Result smalldatetime
declare @MostRecent smalldatetime
set @MostRecent='1/1/1900'
if @Date1>@MostRecent begin set @[email protected] end
if @Date2>@MostRecent begin set @[email protected] end
if @Date3>@MostRecent begin set @[email protected] end
RETURN @MostRecent
종료