SQL에서 최소 두 값 얻기


179

두 가지 변수가 있는데 하나는 PaidThisMonth이고 다른 하나는 OwedPast입니다. 둘 다 SQL의 일부 하위 쿼리 결과입니다. 둘 중 작은 것을 선택하여 제목이 붙은 값으로 반환하려면 어떻게해야 PaidForPast합니까?

MIN함수는 변수가 아닌 열에서 작동합니다.


1
Postgres 또는 MySQL을 사용하는 경우 @Gil_Margolin의 답변으로 건너 뛰십시오.
누 메논

답변:


127

사용 사례 :

   Select Case When @PaidThisMonth < @OwedPast 
               Then @PaidThisMonth Else @OwedPast End PaidForPast

인라인 테이블 값 UDF

CREATE FUNCTION Minimum
(@Param1 Integer, @Param2 Integer)
Returns Table As
Return(Select Case When @Param1 < @Param2 
                   Then @Param1 Else @Param2 End MinValue)

용법:

Select MinValue as PaidforPast 
From dbo.Minimum(@PaidThisMonth, @OwedPast)

부록 : 이것은 가능한 두 개의 값만 처리 할 때 가장 적합 할 것입니다. 둘 이상의 값이있는 경우 값 절을 사용하여 Craig의 답 을 고려하십시오 .


이해하기 쉬운 구문 : return (@ minparam1 <@@ param2 인 경우 @@ param1, 그렇지 않으면 @@ param2 끝인 경우 minValue = case 선택). 좋아, 이것은 정상화되지 않을 수도 있습니다. 그러나 훨씬 이해하기 쉽고 정규화해야합니다.
Softlion

1
아래 @Craig의 답변을 선호하는 또 다른 이유는 null 처리 때문입니다. 비교중인 값이 널 입력 가능하고 비교중인 값 중 하나 가 널인 경우 WHEN 테스트 순서에 따라 표시된 스위치 케이스가 널 또는 값을 리턴 할 수 있습니다 (ISNULL의 사용을 추가하지 않는 한). 크레이그의 접근 방식은 항상 nullable 날짜를 비교할 때 현재 사용 사례에서 null이 아닌 값을 선택하는 것을 선호합니다.
Nij

147

SQL Server 2012 및 2014는 IIF (cont, true, false) 기능을 지원합니다. 따라서 최소한의 선택을 위해 다음과 같이 사용할 수 있습니다

SELECT IIF(first>second, second, first) the_minimal FROM table

IIF 는 글쓰기의 짧은 축약 형 이지만 작성 CASE...WHEN...ELSE하기가 더 쉽습니다.


8
IIF에 대한 구문 설탕입니다 CASE...WHEN...ELSE.
살만 A

55
아마 그렇습니다. 그러나 쓰기가 더 쉽습니다.
Mert Gülsoy

1
@ MertGülsoy 그리고 쉽게 읽을 수 있으며, 정확성 바로 후에 모든 사람의 우선 순위 목록에서 최상위에 있어야합니다.
다니엘

118

CASE, IIF 및 UDF를 사용하는 솔루션이 적합하지만 두 개 이상의 비교 값을 사용하여 문제를 일반적인 경우로 확장 할 때는 비실용적입니다. SQL Server 2008+의 일반화 된 솔루션은 VALUES 절의 이상한 응용 프로그램을 사용합니다.

SELECT
PaidForPast=(SELECT MIN(x) FROM (VALUES (PaidThisMonth),(OwedPast)) AS value(x))

이 웹 사이트로 인한 크레딧 : http://sqlblog.com/blogs/jamie_thomson/archive/2012/01/20/use-values-clause-to-get-the-maximum-value-from-some-columns-sql- server-t-sql.aspx


12
이것이 가장 좋은 답변입니다
FindOutIslamNow

0이 아닌 최소값을 원하면 :MIN(x*(case x when 0 then null else 1 end))
mpag

MartinC를 제외하고는 4 년 전에 같은 대답을했으며 실제로 두 개 이상의 값으로 표시했습니다.
Auspex

4
MartinC의 답변 인 Auspex는 관련이 없습니다. 이 답변은 공용체를 사용하지 않습니다.
Craig

30

방금 업데이트 내에서 최대 4 개의 복잡한 선택을 찾아야하는 상황이있었습니다. 이 방법을 사용하면 원하는만큼 가질 수 있습니다!

숫자를 추가 선택으로 바꿀 수도 있습니다

select max(x)
 from (
 select 1 as 'x' union
 select 4 as 'x' union
 select 3 as 'x' union
 select 2 as 'x' 
 ) a

더 복잡한 사용법

 @answer = select Max(x)
           from (
                select @NumberA as 'x' union
                select @NumberB as 'x' union
                select @NumberC as 'x' union
                select (
                       Select Max(score) from TopScores
                       ) as 'x' 
     ) a

UDF의 성능이 더 좋다고 확신합니다.


기본 SQL이기 때문에 가장 좋아합니다. 또한 UDF가 더 빠를 필요는 없습니다. 대부분의 열 저장소의 경우 각 속성 (속성도 필터링한다고 가정)을 병렬로 계산할 수 있으며 한정 세트 만 통합됩니다. 따라서 노조 자체는 느리지 않습니다.
Bouncner

간단하고 굉장합니다.
ashleedawg

22

MySQL 또는 PostgreSQL 9.3+의 경우 LEASTGREATEST기능 을 사용하는 것이 더 좋습니다 .

SELECT GREATEST(A.date0, B.date0) AS date0, 
       LEAST(A.date1, B.date1, B.date2) AS date1
FROM A, B
WHERE B.x = A.x

와:

  • GREATEST(value [, ...]): 제공된 값에서 가장 큰 (최대 값) 인수를 리턴합니다.
  • LEAST(value [, ...])제공된 값에서 가장 작은 (최소값) 인수를 반환합니다

설명서 링크 :


이것은 또한 PostgreSQL의 작동 (그리고 정확히 내가 :) 참조 찾고 있던 내용은 다음과 같습니다 postgresql.org/docs/9.5/static/functions-conditional.html
알버트 바카 Cintora에게

1
이것이 가장 좋은 답변입니다.
Roberto Rodriguez

2
@RobertoRodriguez 질문에 MySQL 또는 PostgreSQL이 질문의 일부로 태그 된 경우 가장 좋습니다. 질문은 특히 tsql에 관한 것이기 때문에이 답변은 전혀 도움이되지 않습니다.
Jmaurier

이것은 MSSQL에 대한 답변이 아닙니다
Mujah Maskey

13

maximum (field, 0)을 계산하려는 경우 다음과 같은 트릭이 있습니다.

SELECT (ABS(field) + field)/2 FROM Table

field음수 이면 0을 , 그렇지 않으면 0을 반환 field합니다.


3
따라서 최소 (@a, @b)를 계산하려면 다음을 사용할 수 있습니다.SELECT @a - ( ABS(@a-@b) + (@a-@b) ) / 2
scottyc

1
입력 오버 플로우에 대해 잊지 마세요)
pkuderov

이것은 부동 소수점 정밀도 관점에서 저장됩니까? 결과가 절대 0에 가까우면서 부정적이지 않습니까?
zuraff

6

CASE 문을 사용하십시오.

이 페이지의 예제 B는 수행하려는 작업과 비슷해야합니다.
http://msdn.microsoft.com/en-us/library/ms181765.aspx

페이지의 코드는 다음과 같습니다.

USE AdventureWorks;
GO
SELECT   ProductNumber, Name, 'Price Range' = 
      CASE 
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'
         WHEN ListPrice < 50 THEN 'Under $50'
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
         ELSE 'Over $1000'
      END
FROM Production.Product
ORDER BY ProductNumber ;
GO

2

임시 테이블을 사용하여 값 범위를 삽입 한 후 스토어드 프로 시저 또는 UDF에서 임시 테이블의 최소 / 최대를 선택하십시오. 이것은 기본 구성이므로 필요에 따라 수정하십시오.

예를 들면 다음과 같습니다.

CREATE PROCEDURE GetMinSpeed() AS
BEGIN

    CREATE TABLE #speed (Driver NVARCHAR(10), SPEED INT);
    '
    ' Insert any number of data you need to sort and pull from
    '
    INSERT INTO #speed (N'Petty', 165)
    INSERT INTO #speed (N'Earnhardt', 172)
    INSERT INTO #speed (N'Patrick', 174)

    SELECT MIN(SPEED) FROM #speed

    DROP TABLE #speed

END

2

이것은 최대 5 개의 날짜에 작동하며 널을 처리합니다. 인라인 함수로 작동하지 못했습니다.

CREATE FUNCTION dbo.MinDate(@Date1 datetime = Null,
                            @Date2 datetime = Null,
                            @Date3 datetime = Null,
                            @Date4 datetime = Null,
                            @Date5 datetime = Null)
RETURNS Datetime AS
BEGIN
--USAGE select dbo.MinDate('20120405',null,null,'20110305',null)
DECLARE @Output datetime;

WITH Datelist_CTE(DT)
AS (
        SELECT @Date1 AS DT WHERE @Date1 is not NULL UNION
        SELECT @Date2 AS DT WHERE @Date2 is not NULL UNION
        SELECT @Date3 AS DT WHERE @Date3 is not NULL UNION
        SELECT @Date4 AS DT WHERE @Date4 is not NULL UNION
        SELECT @Date5 AS DT WHERE @Date5 is not NULL
   )
Select @Output=Min(DT) FROM Datelist_CTE

RETURN @Output
END

MIN이 Null을 제거하므로 WHERE 절이 필요하지 않습니다.
로렌스

2

mathematix와 scottyc의 훌륭한 논리 / 코드를 바탕으로 다음을 제출합니다.

DECLARE @a INT, @b INT, @c INT = 0

WHILE @c < 100
    BEGIN
        SET @c += 1
        SET @a = ROUND(RAND()*100,0)-50
        SET @b = ROUND(RAND()*100,0)-50
        SELECT @a AS a, @b AS b,
            @a - ( ABS(@a-@b) + (@a-@b) ) / 2 AS MINab,
            @a + ( ABS(@b-@a) + (@b-@a) ) / 2 AS MAXab,
            CASE WHEN (@a <= @b AND @a = @a - ( ABS(@a-@b) + (@a-@b) ) / 2)
            OR (@a >= @b AND @a = @a + ( ABS(@b-@a) + (@b-@a) ) / 2)
            THEN 'Success' ELSE 'Failure' END AS Status
    END

scottyc의 MIN 함수에서 MAX 함수로의 점프는 분명했지만, 해결되지 않았으며 여기에 포함 시켰습니다. SELECT @a + (ABS (@ b- @ a) + ( @ b- @ a)) / 2. 무작위로 생성 된 숫자는 증거는 아니지만 적어도 회의론자들에게 두 공식이 모두 정확하다는 것을 설득해야합니다.

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