如何从表格中获得多个最高值?

时间:2010-10-29 18:20:53

标签: sql sql-server select

我有一张像

这样的表格
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)

7 个答案:

答案 0 :(得分:4)

虽然我不确定如何将它们分成一行,但您可以从:

开始
SELECT * FROM Test ORDER BY f1 DESC LIMIT 3

这应该会给你一个结果:

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

但是,将它们放在一排可能会有点困难......

答案 1 :(得分:3)

在sql server中你可以select top 3 * from Test order by f1 desc。其他DBMS具有类似的可能性,例如MySql的limit,Oracle的rownum等。

答案 2 :(得分:2)

您可以使用ORDER BYTOPPIVOT的组合执行此操作,至少在SQL Server上是这样。似乎许多其他答案都忽略了结果“需要一行”的必要性。

答案 3 :(得分:2)

在T-SQL中的

(即使它们都是相同的值,这也会得到前三个日期)

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]

这将为您提供前三个DISTINCT日期

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

答案 4 :(得分:1)

您要做的事情称为数据透视表,这是一篇关于如何操作的文章:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:766825833740

另外,如果您使用Oracle,我会查看分析函数,特别是OVER PARTITION BY

答案 5 :(得分:1)

这个怎么样?

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不一定按特定顺序排列(根据上面的示例输出)。但这可以以编程方式实现。好的一面是,您可以在WHERE之前插入GROUP BY子句,例如,您可以按T1.id进行搜索。

答案 6 :(得分: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