Sql 如何从表中获取几个最高值?

Sql 如何从表中获取几个最高值?,sql,sql-server,select,Sql,Sql Server,Select,我有一张像这样的桌子 id f1 -------------- 1 2000-01-01 1 2001-01-01 1 2002-01-01 1 2003-01-01 我想把最近的三次约会记录在一起 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)

我有一张像这样的桌子

id  f1
--------------
1   2000-01-01
1   2001-01-01
1   2002-01-01
1   2003-01-01
我想把最近的三次约会记录在一起

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)

虽然我不确定如何将它们放在一行中,但您可以从以下内容开始:

SELECT * FROM Test ORDER BY f1 DESC LIMIT 3
这会给你一个类似的结果:

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

但是,将它们放在一行中可能有点困难…

在sql server中,您可以按f1 desc从测试顺序中选择前3个*。其他数据库管理系统也有类似的功能,如MySql的
limit
、Oracle的
rownum
等。

至少在SQL Server上,您可以通过组合
ORDER BY
TOP
PIVOT
来实现这一点。许多其他答案似乎忽略了结果“全部在一行上”的必要性。

通过数据透视表,如果希望在数据透视后将日期连在一列中,可以获得一行中的前3个日期

编辑: 下面是一个查询,用于透视表并在一行中提供最新的3个日期。但要进行透视,您需要知道表中可用的数据。我想,因为我们查询的是最近3个日期,所以我们不知道围绕日期列旋转的确切数值。首先,我在临时表中查询了最近3个日期。然后在第1、2和3行上运行透视,以获取一行中最近的3个日期

Select Top 3 * into #Temp from Test order by f1 desc 
现在,以行数列为轴心-

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

您正在尝试的操作称为透视表,下面是一篇关于如何操作的文章:

另外,如果您使用Oracle,我将研究分析函数,特别是分区上的函数,这是怎么回事

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 |
+----+------------+------------+------------+
缺点是
date1
date2
date3
不一定按特定顺序排列(根据上述示例输出)。但这可以通过编程实现。有利的一面是,您可以在
GROUP BY
之前插入
WHERE
子句,例如,您可以在T-SQL中通过
T1.id
进行搜索。

(这将获得前三个日期,即使它们的值都相同)

这将为您提供前三个不同的日期

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]
在SQLServer2005中试试这个

--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

为什么一定要排成一行?只有一列会容易得多。我认为将它们作为行返回,而不是一行多列返回更有意义。是否需要每个id的三个最新日期?(我注意到您的id始终为1)编辑:在我的答案中添加了一个查询。并非所有数据库都支持分析—SQL Server 2005+、Oracle 9i+、PostgreSQL 8.4+。。。但不是我,这是行不通的。这将在一列中给出最近的3个日期。Maestro1024要求在一行中输入最新的3个日期。我使用的是MS SQL,这不起作用。语法在MS SQL上是正确的还是无效?@Maestro1024,这只适用于新版本的SQL Server,但它肯定通过了语法检查。@Maestro1024,您使用的是什么版本的MS SQL Server?
--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