[SQL] 여러 열에서 최소 값을 선택하는 가장 좋은 방법은 무엇입니까?
SQL여러 열에서 최소 값을 선택하는 가장 좋은 방법은 무엇입니까?
SQL Server 2005에서 다음 테이블을 감안할 때 :
ID Col1 Col2 Col3
-- ---- ---- ----
1 3 34 76
2 32 976 24
3 7 235 3
4 245 1 792
쿼리를 작성하는 가장 좋은 방법이 무엇 그 수율은 다음과 같은 결과 (즉, 그 하나의 수율 최종 열 - 각 행 COL1, Col2의 밖으로 minium 값을 포함하는 열 및 골) δ
ID Col1 Col2 Col3 TheMin
-- ---- ---- ---- ------
1 3 34 76 3
2 32 976 24 24
3 7 235 3 3
4 245 1 792 1
최신 정보:
실제 시나리오에서 설명 (나는 감동적인에서 말했듯이)에 대한 데이터베이스가 제대로 정상화됩니다. 이러한 "배열"열이 실제 테이블에 아니지만 보고서에 요구되는 결과 집합에 있습니다. 그리고 새로운 요구 사항이 보고서는이 MINVALUE 열을 필요로한다는 것이다. "감옥 카드의 나가"나는 기본 결과 집합을 변경할 수 없습니다, 따라서 나는 편리를위한 T-SQL을 찾고 있었다.
나는 CASE 방법은 아래에 언급과는 조금 복잡하지만 그것이 작동했습니다. 같은 행의 두 분의 값이 있다는 사실을 수용해야하기 때문에 답변에 명시된 것보다 그것은 또한 더 복잡하다.
어쨌든, 난 내 제약 주어진 꽤 잘 작동, 내 현재의 솔루션을 게시 할 거라고 생각했다. 그것은 UNPIVOT 연산자를 사용
with cte (ID, Col1, Col2, Col3)
as
(
select ID, Col1, Col2, Col3
from TestTable
)
select cte.ID, Col1, Col2, Col3, TheMin from cte
join
(
select
ID, min(Amount) as TheMin
from
cte
UNPIVOT (Amount for AmountCol in (Col1, Col2, Col3)) as unpvt
group by ID
) as minValues
on cte.ID = minValues.ID
나는 그것이 (난 그냥 새로운 MINVALUE 열 요구 사항에 대한 모든 쿼리를 재 설계 할 수없는)이 주어진 상황에서 내가 최상의 성능을 제공하기 위해이 기대하지 않는 것이 선행 말하지만,거야 꽤 우아한 "감옥에서 나가 카드".
해결법
-
==============================
1.이 작업을 수행하는 방법에는 여러 가지가 될 가능성이 있습니다. 나의 제안은 케이스를 사용하는 것입니다 / 때 그것을 할 수 있습니다. 3 열, 그것은 나쁘지 않다.
이 작업을 수행하는 방법에는 여러 가지가 될 가능성이 있습니다. 나의 제안은 케이스를 사용하는 것입니다 / 때 그것을 할 수 있습니다. 3 열, 그것은 나쁘지 않다.
Select Id, Case When Col1 < Col2 And Col1 < Col3 Then Col1 When Col2 < Col1 And Col2 < Col3 Then Col2 Else Col3 End As TheMin From YourTableNameHere
-
==============================
2.사용 CROSS이 적용됩니다
사용 CROSS이 적용됩니다
SELECT ID, Col1, Col2, Col3, MinValue FROM YourTable CROSS APPLY (SELECT MIN(d) MinValue FROM (VALUES (Col1), (Col2), (Col3)) AS a(d)) A
SQL 바이올린
-
==============================
3.
SELECT ID, Col1, Col2, Col3, (SELECT MIN(Col) FROM (VALUES (Col1), (Col2), (Col3)) AS X(Col)) AS TheMin FROM Table
-
==============================
4.MySQL의에서이를 사용 :
MySQL의에서이를 사용 :
select least(col1, col2, col3) FROM yourtable
-
==============================
5.당신은 트위스트와 함께 "무력"방법을 사용할 수 있습니다 :
당신은 트위스트와 함께 "무력"방법을 사용할 수 있습니다 :
SELECT CASE WHEN Col1 <= Col2 AND Col1 <= Col3 THEN Col1 WHEN Col2 <= Col3 THEN Col2 ELSE Col3 END AS [Min Value] FROM [Your Table]
첫 번째 경우 조건이 COL1이 가장 작은 값이 아닙니다 보장에 실패하면, 따라서 당신은 조건의 나머지를 제거 할 수 있습니다. 마찬가지로 이후의 조건. 오 열의 쿼리가된다 :
SELECT CASE WHEN Col1 <= Col2 AND Col1 <= Col3 AND Col1 <= Col4 AND Col1 <= Col5 THEN Col1 WHEN Col2 <= Col3 AND Col2 <= Col4 AND Col2 <= Col5 THEN Col2 WHEN Col3 <= Col4 AND Col3 <= Col5 THEN Col3 WHEN Col4 <= Col5 THEN Col4 ELSE Col5 END AS [Min Value] FROM [Your Table]
참고 두 개 이상의 다음 열 <= 우리는 가능한 한 빨리으로 CASE 문을 종료 보장 사이에 넥타이가있는 경우.
-
==============================
6.그것은 사람들이 그냥하면 원하는 결과를 달성하기 훨씬 쉬운 방법이있는 의미있는 정보를 추출하는 SQL "체조"를 요구하는 방법으로, 자신의 데이터를 저장 주장하는 것이 이상하다 - 그렇게 할 수있는 가장 좋은 방법은 그것을 할 수 없습니다 아마 조금 더 나은 스키마를 구성 :-)
그것은 사람들이 그냥하면 원하는 결과를 달성하기 훨씬 쉬운 방법이있는 의미있는 정보를 추출하는 SQL "체조"를 요구하는 방법으로, 자신의 데이터를 저장 주장하는 것이 이상하다 - 그렇게 할 수있는 가장 좋은 방법은 그것을 할 수 없습니다 아마 조금 더 나은 스키마를 구성 :-)
이 작업을 수행하는 올바른 방법은, 내 의견으로는, 다음 표를하는 것입니다 :
ID Col Val -- --- --- 1 1 3 1 2 34 1 3 76 2 1 32 2 2 976 2 3 24 3 1 7 3 2 235 3 3 3 4 1 245 4 2 1 4 3 792
ID와 / 골은 기본 키로 (여분의 키와 가능성이 골, 필요에 따라). 그런 다음 쿼리 TBL에서 간단한 선택 분 (발을)이되고 당신은 여전히 사용하여 별도로 개인의 오래된 열을 '취급 할 수있는 다른 쿼리에서 COL = 2. 이것은 또한 '옛 열'의 수는 증가 할 전망 쉽게 확장 할 수 있습니다.
이 쿼리 훨씬 쉬워집니다. 만약 당신이 데이터베이스 행의 배열처럼 보이는, 당신은 아마 뭔가 잘못하고 있다는 것을 뭔가를하고 데이터를 구조 조정에 대해 생각해야한다면 내가 사용하는 경향이 일반적인 가이드 라인이다.
어떤 이유로 당신이 그 열을 변경할 수없는 경우에는, 나는 삽입 및 업데이트 트리거를 사용하는 것이 좋습니다 이러한 트리거가 COL1 / 2 / 3에 최소로 설정 다른 열을 추가 할 것입니다. 이 거리에서 작업의 '비용'으로 이동하여 자신이 속한 갱신 / 삽입을 선택합니다 - 훨씬 더 자주 쓰기에 비용을 초래하는 것은 시간이 지남에 따라 더 효율적 경향이 있으므로 기록보다 읽어 내 경험에서 대부분의 데이터베이스 테이블.
다른 열 중 하나가 변경 될 때 즉, 행의 최소 단의 당신은, (데이터가 변경되지 않은 경우 낭비)를 선택 할 때마다 그것을하지 계산해야 할 때 그래서, 변경합니다. 그런 다음 테이블 등으로 끝낼 것입니다 :
ID Col1 Col2 Col3 MinVal -- ---- ---- ---- ------ 1 3 34 76 3 2 32 976 24 24 3 7 235 3 3 4 245 1 792 1
다른 컬럼의 추가는 DB에 더 많은 공간을 차지하고 삽입을 위해 약간 느립니다 - 데이터 만 삽입 / 업데이트에 변경하기 때문에 선택시 의사 결정을하는 다른 옵션은 성능 현명한 일반적으로 나쁜 생각 업데이트는하지만, 훨씬 빠른 선택이 될 수 있습니다 - 명시된 선호하는 방법은,이 우선 순위에 의존해야하지만, 대부분의 테이블은 훨씬 더 자주 쓸 것보다 읽습니다.
-
==============================
7.열이 정수는 당신의 예에서와 같이 인 경우에 나는 함수를 만들 것입니다 :
열이 정수는 당신의 예에서와 같이 인 경우에 나는 함수를 만들 것입니다 :
create function f_min_int(@a as int, @b as int) returns int as begin return case when @a < @b then @a else coalesce(@b,@a) end end
나는 그것을 사용할 필요가 다음 때 나는 할 것이다 :
select col1, col2, col3, dbo.f_min_int(dbo.f_min_int(col1,col2),col3)
위에서되고보다 당신은 5 열이있는 경우
select col1, col2, col3, col4, col5, dbo.f_min_int(dbo.f_min_int(dbo.f_min_int(dbo.f_min_int(col1,col2),col3),col4),col5)
-
==============================
8.또한 통합 쿼리와 함께이 작업을 수행 할 수 있습니다. 열 수가 증가, 당신은 쿼리를 수정해야하지만, 적어도 그것은 바로 앞으로 수정 될 것입니다.
또한 통합 쿼리와 함께이 작업을 수행 할 수 있습니다. 열 수가 증가, 당신은 쿼리를 수정해야하지만, 적어도 그것은 바로 앞으로 수정 될 것입니다.
Select T.Id, T.Col1, T.Col2, T.Col3, A.TheMin From YourTable T Inner Join ( Select A.Id, Min(A.Col1) As TheMin From ( Select Id, Col1 From YourTable Union All Select Id, Col2 From YourTable Union All Select Id, Col3 From YourTable ) As A Group By A.Id ) As A On T.Id = A.Id
-
==============================
9.이 브 루트 포스하지만 작품입니다
이 브 루트 포스하지만 작품입니다
select case when col1 <= col2 and col1 <= col3 then col1 case when col2 <= col1 and col2 <= col3 then col2 case when col3 <= col1 and col3 <= col2 then col3 as 'TheMin' end from Table T
... 분 () 하나의 열이 아닌 열에서 작동하기 때문이다.
-
==============================
10.이 질문에 두 그리고이 질문이 대답하려고합니다.
이 질문에 두 그리고이 질문이 대답하려고합니다.
정리 해보에서는 SQL Server와 당신이 붙어 있으며, 오라클은이를 위해 기능이 내장되어 있다는 것입니다 중 하나를 사용자 정의 함수를 정의하거나 경우 문을 사용.
-
==============================
11.여러 열 최선은 두 개의 숫자 열에 대한 그러나, CASE 문을 사용하려면 i와 j 당신은 간단한 계산을 사용할 수 있습니다 :
여러 열 최선은 두 개의 숫자 열에 대한 그러나, CASE 문을 사용하려면 i와 j 당신은 간단한 계산을 사용할 수 있습니다 :
분 (I, J) = (I + J) / 2 - ABS (I-J) / 2
이 수식은 여러 열의 최소 값을 얻기 위해 사용될 수 있지만 실제로는 것, (2) 과거 분 분 (i, j, k)를 질러 (I, 분 (j, K))
-
==============================
12.저장 프로 시저를 만들 수 있다면, 그것은 값의 배열을 걸릴 수 있습니다, 당신은 그냥 전화를 할 수있다.
저장 프로 시저를 만들 수 있다면, 그것은 값의 배열을 걸릴 수 있습니다, 당신은 그냥 전화를 할 수있다.
-
==============================
13.
select *, case when column1 < columnl2 And column1 < column3 then column1 when columnl2 < column1 And columnl2 < column3 then columnl2 else column3 end As minValue from tbl_example
-
==============================
14.노조 쿼리에 작은 트위스트 :
노조 쿼리에 작은 트위스트 :
DECLARE @Foo TABLE (ID INT, Col1 INT, Col2 INT, Col3 INT) INSERT @Foo (ID, Col1, Col2, Col3) VALUES (1, 3, 34, 76), (2, 32, 976, 24), (3, 7, 235, 3), (4, 245, 1, 792) SELECT ID, Col1, Col2, Col3, ( SELECT MIN(T.Col) FROM ( SELECT Foo.Col1 AS Col UNION ALL SELECT Foo.Col2 AS Col UNION ALL SELECT Foo.Col3 AS Col ) AS T ) AS TheMin FROM @Foo AS Foo
-
==============================
15.당신은 SQL 2005을 사용하는 경우는 다음과 같이 깔끔한 일을 할 수 있습니다 :
당신은 SQL 2005을 사용하는 경우는 다음과 같이 깔끔한 일을 할 수 있습니다 :
;WITH res AS ( SELECT t.YourID , CAST(( SELECT Col1 AS c01 , Col2 AS c02 , Col3 AS c03 , Col4 AS c04 , Col5 AS c05 FROM YourTable AS cols WHERE YourID = t.YourID FOR XML AUTO , ELEMENTS ) AS XML) AS colslist FROM YourTable AS t ) SELECT YourID , colslist.query('for $c in //cols return min(data($c/*))').value('.', 'real') AS YourMin , colslist.query('for $c in //cols return avg(data($c/*))').value('.', 'real') AS YourAvg , colslist.query('for $c in //cols return max(data($c/*))').value('.', 'real') AS YourMax FROM res
당신은 너무 많은 사업자에서 길을 잃지 않는이 방법 :)
그러나, 이것은 다른 선택보다 느릴 수 있습니다.
그것은 당신의 선택입니다 ...
-
==============================
16.나는 임시 테이블을 사용하여 아래 여러 날짜의 최소를 얻을 수 있습니다. 첫 번째 임시 테이블은 두 번째 임시 테이블은 다양한 열 및 날짜 열이 있기 때문에 많은 패스로 사용하여 최소 날짜를 가져옵니다 다양한 날짜를 얻을 테이블 (뿐만 아니라 쿼리에 대한 다른 값을) 여러 합류 쿼리합니다.
나는 임시 테이블을 사용하여 아래 여러 날짜의 최소를 얻을 수 있습니다. 첫 번째 임시 테이블은 두 번째 임시 테이블은 다양한 열 및 날짜 열이 있기 때문에 많은 패스로 사용하여 최소 날짜를 가져옵니다 다양한 날짜를 얻을 테이블 (뿐만 아니라 쿼리에 대한 다른 값을) 여러 합류 쿼리합니다.
이것은 기본적으로 통합 쿼리와 같이 패스의 같은 번호가 필요하지만,보다 효율적으로 할 수있다 (경험을 바탕으로하지만, 테스트를해야합니다). 효율성이 경우 (8,000 기록)의 문제가 아니었다. 하나는 인덱스 등을 할 수
--==================== this gets minimums and global min if object_id('tempdb..#temp1') is not null drop table #temp1 if object_id('tempdb..#temp2') is not null drop table #temp2 select r.recordid , r.ReferenceNumber, i.InventionTitle, RecordDate, i.ReceivedDate , min(fi.uploaddate) [Min File Upload], min(fi.CorrespondenceDate) [Min File Correspondence] into #temp1 from record r join Invention i on i.inventionid = r.recordid left join LnkRecordFile lrf on lrf.recordid = r.recordid left join fileinformation fi on fi.fileid = lrf.fileid where r.recorddate > '2015-05-26' group by r.recordid, recorddate, i.ReceivedDate, r.ReferenceNumber, i.InventionTitle select recordid, recorddate [min date] into #temp2 from #temp1 update #temp2 set [min date] = ReceivedDate from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid where t1.ReceivedDate < [min date] and t1.ReceivedDate > '2001-01-01' update #temp2 set [min date] = t1.[Min File Upload] from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid where t1.[Min File Upload] < [min date] and t1.[Min File Upload] > '2001-01-01' update #temp2 set [min date] = t1.[Min File Correspondence] from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid where t1.[Min File Correspondence] < [min date] and t1.[Min File Correspondence] > '2001-01-01' select t1.*, t2.[min date] [LOWEST DATE] from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid order by t1.recordid
-
==============================
17.
SELECT [ID], ( SELECT MIN([value].[MinValue]) FROM ( VALUES ([Col1]), ([Col1]), ([Col2]), ([Col3]) ) AS [value] ([MinValue]) ) AS [MinValue] FROM Table;
-
==============================
18.당신은 당신이 보통 상태 코드, 찾고있는 값을 알고 있다면, 다음이 도움이 될 수 있습니다 :
당신은 당신이 보통 상태 코드, 찾고있는 값을 알고 있다면, 다음이 도움이 될 수 있습니다 :
select case when 0 in (PAGE1STATUS ,PAGE2STATUS ,PAGE3STATUS, PAGE4STATUS,PAGE5STATUS ,PAGE6STATUS) then 0 else 1 end FROM CUSTOMERS_FORMS
-
==============================
19.나는 그 질문은 오래 알고 있지만 나는 대답의 필요성에 아직도 내가 @ paxdiablo's 대답에 트위스트 인 내 자신을 고안했다, 그래서 다른 답변에 만족하지 않았다.
나는 그 질문은 오래 알고 있지만 나는 대답의 필요성에 아직도 내가 @ paxdiablo's 대답에 트위스트 인 내 자신을 고안했다, 그래서 다른 답변에 만족하지 않았다.
나는 SAP ASE 16.0의 땅에서오고, 난 단지 이럴 유효 하나의 행의 다른 컬럼에 저장되어있는 특정 데이터의 통계를 들여다 필요 (그들은 다른 시간을 나타내는 - 뭔가 도착을 계획 할 때,이 때 예상 있었는지 작업이 시작하고 마지막으로) 실제 시간 것이었다. 따라서 나는 임시 테이블의 행으로 전치 열을했다 일반적으로이 이상 내 쿼리를 미리 형성.
N.B. 아니 획일적 인 솔루션 앞서!
CREATE TABLE #tempTable (ID int, columnName varchar(20), dataValue int) INSERT INTO #tempTable SELECT ID, 'Col1', Col1 FROM sourceTable WHERE Col1 IS NOT NULL INSERT INTO #tempTable SELECT ID, 'Col2', Col2 FROM sourceTable WHERE Col2 IS NOT NULL INSERT INTO #tempTable SELECT ID, 'Col3', Col3 FROM sourceTable WHERE Col3 IS NOT NULL SELECT ID , min(dataValue) AS 'Min' , max(dataValue) AS 'Max' , max(dataValue) - min(dataValue) AS 'Diff' FROM #tempTable GROUP BY ID
이 630,000 행의 소스 세트에 약 30 초 걸렸 만 인덱스 데이터, 시간이 중요한 과정에 있지만, 한 번 데이터 검사 또는 엔드 - 중 - 일 보고서 당신이 될 수 같은 것들에 대한 실행 그렇게하지 않는 것을 사용 좋은 (그러나 동료 나 상사, 제발로이를 확인!). 나를 위해이 스타일의 홈페이지 보너스 내가 쉽게 데이터를 통해 copyied하고 특히 한번 더 / 덜 열 변화 등, 그룹화 필터링을 사용할 수있는 것이 었습니다.
추가 데이터 (COLUMNNAME, maxes는 ...) 당신이 그들을 필요로하지 않을 수 있습니다, 그래서 내 검색에서 저를 돕기 위해이었다; 어쩌면 몇 가지 아이디어를 촉발하기 위해 여기를 떠나 :-).
from https://stackoverflow.com/questions/368351/whats-the-best-way-to-select-the-minimum-value-from-several-columns by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] MySQL은 비교 날짜 (0) | 2020.04.14 |
---|---|
[SQL] SQLite는 무작위 행 (들)을 선택 (0) | 2020.04.14 |
[SQL] 포스트 그레스 - 컬럼에 트랜스 행 (0) | 2020.04.14 |
[SQL] 오라클 SQL, CONCATENATE 여러 열 + 텍스트 추가 (0) | 2020.04.14 |
[SQL] 합계로 요약 행 추가 (0) | 2020.04.14 |