여러 열의 SQL MAX?


372

여러 열의 최대 행당 1 값을 어떻게 반환합니까?

TableName

[Number, Date1, Date2, Date3, Cost]

다음과 같은 것을 반환해야합니다.

[Number, Most_Recent_Date, Cost]

질문?

답변:


161

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의 더 간단한 답변을 고려할 수 있습니다.]


11
사용하기에 충분하지 WHEN Date1 > Date2 AND Date1 > Date3 THEN Date1; WHEN Date2 > Date3 THEN Date3; ELSE Date3않습니까?
Treb

21
명백한 대답이지만 NULL 값으로는 작동하지 않으며 수정하려고하면 매우 지저분 해집니다.
환멸

5
이 오래된 게시물을 Necro'ing하지만 NULL을 처리하기 위해 각 날짜를 COALESCE로 래핑 할 수 있습니다. 문은 다음과 같을 것이다 언제 그 중 하나 날짜 1> = COALESCE (DATE2, '') 및 날짜 1> = COALESCE (Date3, '') THEN Date3는 (다른 동일한 작업을 수행 할 때의)
빌 Sambrone

여기에 MySQL 방식을 찾는 사람들은 @ bajafresh4life 회신을보십시오. stackoverflow.com/a/331873/1412157
LucaM

2
BTW, Date3> Date1이더라도 Date2가 null이면 Date1을 반환합니다.
jumxozizi

853

다음은 MaxT-SQL 및 SQL Server를 사용 하는 기능에 대한 또 다른 훌륭한 솔루션입니다.

SELECT [Other Fields],
  (SELECT Max(v) 
   FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]

47
SQL 버전은> = 2008이어야합니다.
Daniel

10
이것은 2008에서 잘 작동하며 NULL을 처리합니다. 아주 좋은 해결책.
nycdan

10
@Cheburek : value (v)에서 "value"는 가상 테이블의 별명이고 "v"는 날짜 값의 가상 열 이름입니다.
Jonas Lincoln

2
훌륭합니다. 이 Value () 가상 테이블에 대한 설명서는 어디서 찾을 수 있습니까?
My Other Me

33
처음에는 VALUE (v)도 이해하지 못했습니다. VALUE를 이해하려면 가상 1 컬럼 테이블을 작성하는 다음 쿼리를 시도하십시오. SELECT * FROM (VALUES (1), (5), (1)) as listOfValues ​​(columnName).이 조회는 가상 2 컬럼 테이블을 작성합니다. SELECT * FROM (VALUES (1,2), (5,3), (1,4)) as tableOfValues ​​(columnName1, ColumnName2) 이제 샘플 쿼리에 AS 값 (v)이있는 이유를 이해할 수 있습니다. 최종 쿼리는 다음과 같습니다. SELECT Max (currentValues) as Max FROM (VALUES (12), (25), (35)) AS allCurrents (currentValues)이 경우 최대 값을 선택합니다.이 경우 35입니다.
Jackson

148

MySQL을 사용하는 경우 사용할 수 있습니다

SELECT GREATEST(col1, col2 ...) FROM table

41
태그 SQLSERVER입니다
Codewerks

104
사람들이 MySQL과 관련 하여이 질문을 찾은 사실이지만 여전히 유용한 답변입니다.
philfreo

4
8.1 이후 PostgreSQL에서도 사용 가능 합니다.
Frozen Flame

4
NULL을 잘 처리하지는 않지만 열 값 주위에서 병합 (col1, 0)하면 가스로 요리 할 것입니다 stackoverflow.com/questions/9831851/…
Stan Quinn

이 솔루션은 어떻
습니까

64

3 개 방법이 있습니다 UNPIVOT훨씬 느린 (1)보다 시뮬레이션 피벗 해제 (3) 다음 (1) 지금까지 가장 빠른이지만, 여전히보다 빠른 (2)

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

해결책 1 ( UNPIVOT)

SELECT  number ,
        MAX(dDate) maxDate ,
        cost
FROM    dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,
                                            Date3 ) ) as u
GROUP BY number ,
        cost 
GO

솔루션 2 (행당 하위 쿼리)

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

솔루션 3 (Simulated 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

1
좋은. 나는 PIVOT과 UNPIVOT 운영자를 알지 못했습니다.
Sako73

피벗 / 피벗 해제를 지원하는 SQL Server 버전을 알고 있습니까?
환멸

1
COMPATIBILITY_LEVEL이 90으로 설정된 @CraigYoung SQL Server 2005
폴 Syfrett에게

18

아래 두 샘플 중 하나가 작동합니다.

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의 답변 .

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 

첫 번째 대답은 좋지만 크게 단순화 할 수 있습니다. 두 번째 답변은 NULL 값으로 작동하지 않습니다. 이 문제를 해결하려고하면 매우 지저분해진다.
환멸

불필요한 암시 적 DISTINCT 조작을 피하려면 UNION이 아닌 UNION ALL을 사용해야합니다.
JamieSee

17

T-SQL의 경우 (MSSQL 2008+)

SELECT
  (SELECT
     MAX(MyMaxName) 
   FROM ( VALUES 
            (MAX(Field1)), 
            (MAX(Field2)) 
        ) MyAlias(MyMaxName)
  ) 
FROM MyTable1

9
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

나를 위해 모든 SQL 버전
Kirill

9

스칼라 함수는 모든 종류의 성능 문제를 유발하므로 가능한 경우 논리를 인라인 테이블 값 함수에 래핑하는 것이 좋습니다. 이것은 최대 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)
)

5
SELECT 
    CASE 
        WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1 
        WHEN Date2 >= Date3 THEN Date2 
        ELSE Date3
    END AS MostRecentDate 

사례 설명이 순서대로 평가되므로 작성하기가 약간 쉽고 평가 단계를 건너 뜁니다.


4
꼼꼼한. Date2가 NULL이면 답은 Date3입니다. Date1이 더 큰 경우에도 마찬가지입니다.
08에 환멸

4

불행히도 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

4

문제 : 엔터티에 제공된 최소 요율 값을 선택합니다. 요구 사항 : 대행사 요율은 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 

Nat의 답변 에서 영감을 얻었습니다.


3

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

1
UNION 예제를 더 좋아한다고 생각합니다.
랜스 피셔

"여러 열의 최대
행당

3

CROSS APPLY 사용 (2005+ 이상) ....

SELECT MostRecentDate 
FROM SourceTable
    CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md

3

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

꽤 좋지만 null을 처리하지 않습니다. 예 :DECLARE @Date1 DATE='2014-08-01'; DECLARE @Date2 DATE=null; DECLARE @Date3 DATE='2014-07-05'; /*this gets returned*/
jumxozizi

: 우리는이 같은 널 (null) 처리 할 수select IIF(@Date1 > @Date2 or @Date2 is null, IIF(@Date1 > @Date3 or @Date3 is null, @Date1, @Date3), IIF(@Date2 > @Date3 or @Date3 is null, @Date2, @Date3)) as MostRecentDate
jumxozizi

1

사용하십시오 UNPIVOT:

SELECT MAX(MaxDt) MaxDt
   FROM tbl 
UNPIVOT
   (MaxDt FOR E IN 
      (Date1, Date2, Date3)
)AS unpvt;

1

나는 경우에 따라 솔루션을 선호합니다. 제 적용은 크로스 적용, 값 (), 사용자 정의 함수 등이있는 다른 가능한 솔루션과 비교하여 가능한 성능 저하에 가장 적은 영향을 미칩니다.

다음은 가능한 대부분의 테스트 사례로 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

1
오 신 이시여 감사합니다! 나는 아직도 나에게 null을주는 괴물 공식 의이 지옥을하는 데 많은 시간을 보냈고 이제 터널 끝에서 빛을 봅니다.
Max S.

0

날짜를 전달하는 함수를 만든 다음 아래처럼 select 문에 함수를 추가 할 수 있습니다. 숫자, dbo.fxMost_Recent_Date (Date1, Date2, Date3), 비용을 선택하십시오.

create FUNCTION  fxMost_Recent_Date 

(@ Date1 smalldatetime, @ Date2 smalldatetime, @ Date3 smalldatetime) BEGIN DECLARE @Result smalldatetime으로 smalldatetime을 반환합니다.

declare @MostRecent smalldatetime

set @MostRecent='1/1/1900'

if @Date1>@MostRecent begin set @MostRecent=@Date1 end
if @Date2>@MostRecent begin set @MostRecent=@Date2 end
if @Date3>@MostRecent begin set @MostRecent=@Date3 end
RETURN @MostRecent

종료


0

http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.htmlScottPletcher 솔루션을 기반으로 최대 기능을 찾기 위해 일련의 기능 (예 : GetMaxOfDates3, GetMaxOfDates13)을 만들었습니다. UNION ALL을 사용하여 최대 13 개의 날짜 값. 같은 행에서 최대 값을 얻으려면 T-SQL 함수를 참조하십시오. 그러나 나는이 함수를 작성할 때 UNPIVOT 솔루션을 고려하지 않았습니다.


0

CASE WHEN 을 사용하는 다른 방법

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

-1

여기에 이미지 설명을 입력하십시오위의 표는 salary1, salary2, salary3, salary4를 열로 사용하는 직원 급여 테이블입니다. 아래 쿼리는 4 개의 열 중 최대 값을 반환합니다.

select  
 (select Max(salval) from( values (max(salary1)),(max(salary2)),(max(salary3)),(max(Salary4)))alias(salval)) as largest_val
 from EmployeeSalary

위의 쿼리를 실행하면 출력이 biggest_val (10001)로 나타납니다.

위 쿼리의 논리는 다음과 같습니다.

select Max(salvalue) from(values (10001),(5098),(6070),(7500))alias(salvalue)

출력은 10001입니다


이것은 @ sven
Luuk

-3

다음은 좋은 해결책입니다.

CREATE function [dbo].[inLineMax] (@v1 float,@v2 float,@v3 float,@v4 float)
returns float
as
begin
declare @val float
set @val = 0 
declare @TableVal table
(value float )
insert into @TableVal select @v1
insert into @TableVal select @v2
insert into @TableVal select @v3
insert into @TableVal select @v4

select @val= max(value) from @TableVal

return @val
end 

-3

M $ ACCESS 도움말에 SQL 등이 있는지 여부는 알 수 없습니다 MAXA(Value1;Value2;...). 그런 함수를 호출 해야합니다.

희망은 누군가를 도울 수 있습니다.

PD : 값은 열 또는 계산 된 값 등일 수 있습니다.


1
Microsoft Access는 완전히 다른 제품입니다. 게다가, 당신은 그러한 기능에 대한 당신의 주장을 이끌어 낼 수 있습니까? Access에서 이것을 보거나들은 적이 없습니다.
deutschZuid

1
MAXAAccess 가 아닌 Excel 함수 입니다.
Felix Eve
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.