2010-10-29 107 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