programing

여러 열의 SQL MAX?

yoursource 2023. 4. 7. 22:29
반응형

여러 열의 SQL MAX?

여러 열의 최대값 중 행당 하나의 값을 반환하려면 어떻게 해야 합니까?

테이블명

[Number, Date1, Date2, Date3, Cost]

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

[Number, Most_Recent_Date, Cost]

질문?

또 좋은 .Max 및 을 사용한

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

값은 테이블생성자입니다.

"테이블로 구성할 행 값 식 집합을 지정합니다.Transact-SQL 테이블 값 생성자를 사용하면 단일 DML 문에서 여러 행의 데이터를 지정할 수 있습니다.테이블 값 생성자는 INSERT...의 VALUES 절로 지정할 수 있습니다.VALUES 스테이트먼트 또는 MERGE 스테이트먼트의 USING 절 또는 FROM 절 중 하나의 파생 테이블로 사용할 수 있습니다."

MySQL 또는 Postgre를 사용하는 경우SQL, Oracle 또는 BigQuery를 사용할 수 있습니다.

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

이것은 오래된 대답이고 여러모로 깨졌다.

https://stackoverflow.com/a/6871572/194653 를 참조해 주세요.https://stackoverflow.com/a/6871572/194653 는, 보다 많은 업베이트가 있어 sql server 2008+ 와 연동해, 늘(null)

독창적이지만 문제가 있는 답변:

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

세 이 더 요.UNPIVOT1)이, 으로 (1 (2)보다훨씬 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

1 (루 ( 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 ()3 (시뮬레이션)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

스칼라 함수는 모든 종류의 성능 문제를 일으키므로 가능하면 인라인 테이블 값 함수로 논리를 정리하는 것이 좋습니다.이 함수는 최대 10개의 날짜 목록에서 최소/최대 날짜를 선택한 일부 사용자 정의 함수를 대체하는 데 사용되었습니다.100만 행의 데이터 세트로 테스트한 결과, 스칼라 함수는 쿼리를 종료하기 전에 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)
)

다음의 2개의 샘플 중 하나가 동작합니다.

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 

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 

이것은, 케이스 스테이트먼트가 순서대로 평가되기 때문에, 기입이 조금 쉬워지고 평가 스텝은 생략됩니다.

불행하게도 라세의 대답은 겉으로 보기에는 분명하지만 결정적인 결함이 있다.NULL 값은 처리할 수 없습니다.단일 NULL 값을 지정하면 Date1이 반환됩니다.안타깝게도 이 문제를 해결하려는 시도는 매우 혼란스러워지기 쉽고 4개 이상의 값으로 확장되지 않습니다.

databys의 번째 답변은 좋아보였습니다.그러나 하나의 테이블에서 단순한 3개의 값이 아닌 다중 테이블 결합에서 3개의 값으로 쉽게 추정할 수 있을지는 명확하지 않습니다.나는 단지 3컬럼의 최대치를 얻기 위해 이러한 쿼리를 서브쿼리로 바꾸는 것을 피하고 싶었고, 또한 데이터 시스템의 훌륭한 아이디어가 약간 정리될 것이라고 확신했다.

자, 이제 더 이상 말하지 말고, (데이터베이스의 아이디어에서 파생된) 솔루션을 제시하겠습니다.
교차 결합 선택 상수를 사용하여 다중 테이블 결합의 효과를 시뮬레이션합니다.주의할 점은 필요한 에일리어스가 모두 올바르게 전달된다는 것입니다(항상 그렇지는 않습니다).이것에 의해, 패턴을 심플하게 해, 추가 열을 통해서 꽤 측정할 수 있게 됩니다.

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 

NAT의 이 답변에 영감을 받아

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

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 2022 (16.x) 미리보기
  • Azure SQL 데이터베이스
  • Azure SQL 관리 인스턴스

GREATE도 사용할 수 있습니다.다른 T-SQL 함수와 마찬가지로 몇 가지 중요한 주의사항을 다음에 제시하겠습니다.

  • 모든 인수가 동일한 데이터 유형을 가지며 그 유형이 비교용으로 지원되는 경우 GREAST는 해당 유형을 반환합니다.
  • 그렇지 않으면 함수는 모든 인수를 비교 전에 가장 우선순위가 높은 데이터 유형으로 암묵적으로 변환하고 이 유형을 반환 유형으로 사용합니다.
  • 하나 이상의 인수가 NULL이 아닌 경우 비교 시 NULL 인수는 무시됩니다.모든 인수가 NULL인 경우 GREATE는 NULL을 반환합니다.

8,000바이트를 초과하는 varchar(max), varbinary(max) 또는 nvarchar(max), 커서, 지오메트리, 지리, 이미지, 바이트가 아닌 사용자 정의 유형, ntext, table, text 및 xml의 비교에는 지원되지 않습니다.

사용해보시기 바랍니다.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

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

CREATE FUNCTION GetMaxOfDates13 (
@value01 DateTime = NULL,  
@value02 DateTime = NULL,
@value03 DateTime = NULL,
@value04 DateTime = NULL,
@value05 DateTime = NULL,
@value06 DateTime = NULL,
@value07 DateTime = NULL,
@value08 DateTime = NULL,
@value09 DateTime = NULL,
@value10 DateTime = NULL,
@value11 DateTime = NULL,
@value12 DateTime = NULL,
@value13 DateTime = NULL
)
RETURNS DateTime
AS
BEGIN
RETURN (
SELECT TOP 1 value
FROM (
SELECT @value01 AS value UNION ALL
SELECT @value02 UNION ALL
SELECT @value03 UNION ALL
SELECT @value04 UNION ALL
SELECT @value05 UNION ALL
SELECT @value06 UNION ALL
SELECT @value07 UNION ALL
SELECT @value08 UNION ALL
SELECT @value09 UNION ALL
SELECT @value10 UNION ALL
SELECT @value11 UNION ALL
SELECT @value12 UNION ALL
SELECT @value13
) AS [values]
ORDER BY value DESC    
)
END –FUNCTION
GO
CREATE FUNCTION GetMaxOfDates3 (
@value01 DateTime = NULL,  
@value02 DateTime = NULL,
@value03 DateTime = NULL
)
RETURNS DateTime
AS
BEGIN
RETURN dbo.GetMaxOfDates13(@value01,@value02,@value03,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
END –FUNCTION

날짜를 전달한 후 아래와 같이 선택문에 함수를 추가할 수 있습니다.숫자, dbo.fxMost_Recent_Date(날짜 1, 날짜 2, 날짜 3), 비용 선택

create FUNCTION  fxMost_Recent_Date 

(@Date1 smaldatime, @Date2 smaldatime, @Date3 smaldatime ) smaldatime AS BEGIN DECLARE @Result smaldatime을 반환합니다.

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

끝.

CASE를 사용하는 다른 방법:

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

이 솔루션에서는 null 값 비교도 처리할 수 있습니다.하나의 쿼리로 작성하면 간단하게 할 수 있지만, 설명을 위해 CTE를 사용하고 있습니다.스텝 1에서는 비교를 3에서2로, 스텝 2에서는 2에서1로 줄이는 것입니다.

with x1 as
(
  select 1 as N1, null as N2, 3 as N3
  union
  select 1 as N1, null as N2, null as N3
  union
  select null as N1, null as N2, null as N3
)
,x2 as
(
select 
N1,N2,N3,
IIF(Isnull(N1,0)>=Isnull(N2,0),N1,N2) as max1,
IIF(Isnull(N2,0)>=Isnull(N3,0),N2,N3) as max2
from x1
)
,x3 as
(
 select N1,N2,N3,max1,max2,
 IIF(IsNull(max1,0)>=IsNull(max2,0),max1,max2) as MaxNo
 from x2
)
select * from x3

출력:

여기에 이미지 설명 입력

여기 좋은 해결책이 있습니다.

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 

SQL 등에 있는지...M$ACCESS 도움말에는 다음과 같은 함수가 있습니다.MAXA(Value1;Value2;...)그렇게 하기로 되어 있어요.

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

P.D.: 값은 열 또는 계산된 값 등이 될 수 있습니다.

여기에 이미지 설명 입력위 표는 급여1, 급여2, 급여3, 급여4를 열로 한 직원 급여표입니다.아래 쿼리는 4개의 열 중 최대값을 반환합니다.

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

위의 쿼리를 실행하면 출력이 bigest_val(10001)로 표시됩니다.

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

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

출력은 10001이 됩니다.

언급URL : https://stackoverflow.com/questions/71022/sql-max-of-multiple-columns

반응형