2010-10-29 111 views
5

我有這樣如何從表中獲得幾個最高值?

id f1 
-------------- 
1 2000-01-01 
1 2001-01-01 
1 2002-01-01 
1 2003-01-01 

一個表,我想說,最近3日在一排

CREATE TABLE Test 
(
    id INT NOT NULL, 
    f1 DATETIME NOT NULL, 
) 

INSERT INTO Test (id, f1) VALUES (1, '1/1/2000') 
INSERT INTO Test (id, f1) VALUES (1, '1/1/2001') 
INSERT INTO Test (id, f1) VALUES (1, '1/1/2002') 
INSERT INTO Test (id, f1) VALUES (1, '1/1/2003') 

SELECT T1.* FROM Test as T1 

試圖像

  SELECT T1.*,T2.* 
      FROM Test AS T1 
LEFT OUTER JOIN Test AS T2 ON T1.id = T2.id AND (T2.f1 > T1.f1) 
+3

爲什麼它必須全部排成一行?只有一列會容易得多。 – 2010-10-29 18:24:20

+1

我認爲將它們作爲行返回更合理,而不是將多行返回1行。 – dotariel 2010-10-29 18:27:21

+0

你需要每個ID的三個最新日期嗎? (我注意到你的ID總是1) – 2010-10-29 19:23:46

回答

3

在SQL Server中,你可以做select top 3 * from Test order by f1 desc。其他DBMS的也有類似的posibilities如MySQL的limit,Oracle的rownum

+0

這不行。這將在一列中給出最新的3個日期。 Maestro1024在一行中要求最新的3個日期。 – pavanred 2010-10-29 19:19:18

3

東西雖然我不是當然如何讓他們成爲一排,你可以從下面開始:

SELECT * FROM Test ORDER BY f1 DESC LIMIT 3 

這應該給你一個結果,如:

id f1 
1 2003-01-01 
1 2002-01-01 
1 2001-01-01 

將它們放入單列,雖然可能有點難度......

2

您可以用ORDER BYTOPPIVOT組合,至少在SQL Server上做到這一點。似乎許多其他答案已經忽略了結果是「全部在一行上」的需要。

0

如果您希望在透視後旋轉一列,則可以通過旋轉該表並連接日期來獲得連續排名前3的日期。

編輯: 這是一個查詢來轉換表並提供連續的最新3個日期。但是爲了支撐你,你需要知道表格中可用的數據。我想,因爲我們正在查詢最新的3個日期,所以我們不會知道在日期列中轉換的確切值。所以首先,我將最新的3個日期查詢到臨時表中。然後在row_number 1,2和3上運行一個數據透視表以獲取連續的最新3個日期。

Select Top 3 * into #Temp from Test order by f1 desc 

現在,在ROW_NUMBER列支點 -

SELECT id,[3] as Latest,[2] as LatestMinus1,[1] as LatestMinus2 
FROM (
select ROW_NUMBER() OVER(ORDER BY f1) AS RowId,f1,id from #Temp) AS Src 
PIVOT (Max(f1) FOR RowId IN ([1],[2],[3])) AS pvt 

這導致 -

Id | Latest     |LatestMinus1    |LatestMinus2 
1 | 2003-01-01 00:00:00.000 | 2002-01-01 00:00:00.000 | 2001-01-01 00:00:00.000 

,當然

drop table #Temp 
+0

編輯:添加一個查詢到我的答案。 – pavanred 2010-10-29 19:17:04

+0

分析並非所有的數據庫支持 - 的SQL Server 2005+,甲骨文9I +和PostgreSQL 8.4 + ...但我使用MS SQL沒有MySQL的 – 2010-10-29 19:23:58

0

這個怎麼樣?

SELECT T1.f1 as "date 1", T2.f1 as "date 2", T3.f1 as "date 3" 
    FROM (SELECT * 
     FROM `date_test` 
     ORDER BY `f1` DESC 
     LIMIT 1) AS T1, 
     (SELECT * 
     FROM `date_test` 
     ORDER BY `f1` DESC 
     LIMIT 1, 1) AS T2, 
     (SELECT * 
     FROM `date_test` 
     ORDER BY `f1` DESC 
     LIMIT 2, 1) AS T3 
; 

,輸出:

+------------+------------+------------+ 
| date 1  | date 2  | date 3  | 
+------------+------------+------------+ 
| 2003-01-01 | 2002-01-01 | 2001-01-01 | 
+------------+------------+------------+ 

唯一的缺點是,你至少需要三人行,否則它不會返回任何東西......

使用JOIN,你可以這樣做:

SELECT T1.id, 
     T1.f1 as "date 1", 
     T2.f1 as "date 2", 
     T3.f1 as "date 3" 
    FROM `date_test` as T1 
    LEFT JOIN (SELECT * FROM `date_test` ORDER BY `f1` DESC) as T2 ON (T1.id=T2.id AND T1.f1 != T2.f1) 
    LEFT JOIN (SELECT * FROM `date_test` ORDER BY `f1` DESC) as T3 ON (T1.id=T3.id AND T2.f1 != T3.f1 AND T1.f1 != T3.f1) 
GROUP BY T1.id 
ORDER BY T1.id ASC, T1.f1 DESC 

這將返回類似於:

+----+------------+------------+------------+ 
| id | date 1  | date 2  | date 3  | 
+----+------------+------------+------------+ 
| 1 | 2001-01-01 | 2003-01-01 | 2002-01-01 | 
+----+------------+------------+------------+ 

缺點是date1date 2date 3不一定會以特定的順序(按照上面的示例輸出)。但這可以通過編程實現。有利的一面是,你可以在GROUP BY前插入一個WHERE條款,您可以通過搜索T1.id,例如。

在T-SQL
1

(這將讓你的前三名日期,即使他們都是相同的值)

with TestWithRowNums(f1, row_num) as 
(
select f1, row_number() over(order by [f1] desc) as row_num from test 
) 
select 
(select [f1] from TestWithRowNums where row_num = 1) as [Day 1], 
(select [f1] from TestWithRowNums where row_num = 2) as [Day 2], 
(select [f1] from TestWithRowNums where row_num = 3) as [Day 3] 

這將讓你頂三個不同的日期

with TestWithRankNums(f1, rank_num) as 
(
select f1, dense_rank() over(order by [f1] desc) as rank_num from test 
) 
select 
(select top 1 [f1] from TestWithRankNums where rank_num = 1) as [Day 1], 
(select top 1 [f1] from TestWithRankNums where rank_num = 2) as [Day 2], 
(select top 1 [f1] from TestWithRankNums where rank_num = 3) as [Day 3] 

嘗試這在SQL Server 2005中

--to get top three values even if they are the same 
select [1] as Day1, [2] as Day2, [3] as Day3 from 
(select top 3 f1, row_number() over(order by [f1] desc) as row_num from test) src 
pivot 
(
max(f1) for row_num in([1], [2], [3]) 
) as pvt 
--to get top three distinct values 
select [1] as Day1, [2] as Day2, [3] as Day3 from 
(select f1, dense_rank() over(order by [f1] desc) as row_num from test) src 
pivot 
(
max(f1) for row_num in([1], [2], [3]) 
) as pvt 
+0

,這是行不通的。 MS SQL的語法是正確還是無效? – Maestro1024 2010-10-29 19:55:22

+0

@ Maestro1024,這隻適用於新版本的SQl服務器,但它肯定會通過語法檢查。 – HLGEM 2010-10-29 20:22:20

+0

@ Maestro1024,你正在使用什麼版本的MS SQL Server? – 2010-10-29 22:29:01