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

发布于 2024-09-29 14:56:54 字数 632 浏览 5 评论 0原文

我有一张像这样的表

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)

I have a table like

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

And I want to get say the latest 3 dates in one row

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

Was trying something like

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

风渺 2024-10-06 14:56:54

虽然我不确定如何将它们放入单行,但您可以从以下开始:

SELECT * FROM Test ORDER BY f1 DESC LIMIT 3

这应该会给您一个类似的结果:

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

不过,将它们放入单行可能会有点困难......

Although I'm not sure how to get them into a single row, you could start with:

SELECT * FROM Test ORDER BY f1 DESC LIMIT 3

That should give you a result like:

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

Putting them into a single row, though, may be a bit more difficult...

浊酒尽余欢 2024-10-06 14:56:54

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

In sql server you could do select top 3 * from Test order by f1 desc. Other DBMS's have similar posibilities such as MySql's limit, Oracle's rownum etc.

一腔孤↑勇 2024-10-06 14:56:54

至少在 SQL Server 上,您可以结合使用 ORDER BYTOPPIVOT 来实现此目的。似乎许多其他答案都忽略了结果“全部在一行”的需要。

You can do this with a combination of ORDER BY, TOP and PIVOT, at least on SQL Server. It seems that many of the other answers have ignored the need for the result to be "all on one row."

时光是把杀猪刀 2024-10-06 14:56:54

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

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

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

in T-SQL (This will get you the top three dates even if they are all the same value)

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]

This will get you the top three DISTINCT dates

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]

Try this in 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
以歌曲疗慰 2024-10-06 14:56:54

您想要做的事情称为数据透视表,这里有一篇关于如何执行此操作的文章:

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

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

What you are trying to do is called pivot table, here is an article on how to do it:

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

also, if you use Oracle I would look at analytic functions, OVER PARTITION BY in particular

怎会甘心 2024-10-06 14:56:54

这又如何呢?

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 进行搜索。

What about this ?

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
;

Which outputs :

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

The only downside is that you need at least three rows, otherwise it won't return anything...

Using JOIN, you can do this :

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

Which will return something like :

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

The downside is that date1, date 2 and date 3 will not necessarily be in a specific order (as per the above sample output). But this can be achieved programatically. The plus side is that you can insert a WHERE clause before the GROUP BY and you can search by T1.id, for example.

阳光下的泡沫是彩色的 2024-10-06 14:56:54

您可以通过旋转表格来获取连续前 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

You can get top 3 dates in a row by pivoting the table and perhaps concatenating the dates if you want them in one column after pivoting.

Edit :
here is a query to pivot the table and provide the latest 3 dates in a row. But to pivot you would need to know the data that is available in the table. I figured since we are querying for the latest 3 dates we will not know the exact vales to pivot around the date column. So First, I queried the latest 3 dates into a temp table. Then ran a pivot on the row_number 1, 2 and 3 to obtain the latest 3 dates in a row.

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

Now, pivot on the row_number column -

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

This results in -

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

And, of course

drop table #Temp
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文