选择列中具有第二高值的行

时间:2021-02-11 12:21:59

Let's say I have a table similar to the following:

假设我有一个类似于以下的表格:

Item         Description            Time
-----        -----------            -----
ItemA1       descript               08-16-2013 00:00:00
ItemA2       descript               08-16-2013 00:00:00
ItemA3       descript               08-16-2013 00:00:00
.
.
ItemAN       descript               08-16-2013 00:00:00

ItemB1       descript               08-13-2013 00:00:00
ItemB2       descript               08-13-2013 00:00:00
ItemB3       descript               08-13-2013 00:00:00
.
.
ItemBN       descript               08-13-2013 00:00:00
.
.
.
ItemX1       descript               01-13-2012 00:00:00
ItemX2       descript               01-13-2012 00:00:00
ItemX3       descript               01-13-2012 00:00:00
.
.
ItemXN       descript               01-13-2012 00:00:00

Groups of items are added periodically. When a group of items is added they are all added with the same "Time" field. "Time" essentially serves as a unique index for that item group.

定期添加项目组。添加一组项目时,它们都添加了相同的“时间”字段。 “时间”基本上作为该项目组的唯一索引。

I want to SELECT the group of items that have the second highest time. In this example my query should pull the "B" items. I know I can do max(time) to SELECT the "A" items, but I don't know how I would do second last.

我想选择时间第二高的项目组。在此示例中,我的查询应拉出“B”项。我知道我可以做最大(时间)选择“A”项,但我不知道我会怎么做到最后。

My "Time" columns are stored as TIMESTAMP if that means anything.

我的“时间”列存储为TIMESTAMP,如果这意味着什么。

9 个解决方案

#1


15  

You can try something like:

您可以尝试以下方法:

SELECT MAX(Time)
FROM yourTable
WHERE Time < (SELECT MAX(Time) FROM yourTable)

SQLFiddle Demo

SQLFiddle演示

#2


7  

One approach:

一种方法:

SELECT t.*
 FROM mytable t
 JOIN ( SELECT l.time
          FROM mytable l
         GROUP BY l.time
         ORDER BY l.time DESC
         LIMIT 1,1 
      ) m
   ON m.time = t.time

This uses an inline view (assigned an alias of m) to return the second "greatest" time value. The GROUP BY gets us a distinct list, the ORDER BY DESC puts the latest first, and the "trick" is the LIMIT, which returns the second row. LIMIT(m,n) = (skip first m rows, return next n rows)

这使用内联视图(指定别名为m)来返回第二个“最大”时间值。 GROUP BY为我们提供了一个独特的列表,ORDER BY DESC将最新的列表放在第一位,而“技巧”则是LIMIT,它返回第二行。 LIMIT(m,n)=(跳过前m行,返回n行)

With that time value, we can join back to the original table, to get all rows that have a matching time value.

使用该时间值,我们可以连接回原始表,以获得具有匹配时间值的所有行。


Performance will be enhanced with an index with leading column of time. (I think MySQL should be able to avoid a "Using filesort" operation, and get the result from the inline view query fairly quickly.)

使用具有领先时间列的索引将增强性能。 (我认为MySQL应该能够避免“使用filesort”操作,并且可以非常快速地从内联视图查询中获取结果。)

But, including a predicate in the inline view query, if you "know" that the second latest time will never be more than a certain number of days old, won't hurt performance:

但是,在内联视图查询中包含谓词,如果您“知道”第二个最新时间永远不会超过一定天数,则不会影响性能:

   WHERE l.time > NOW() + INTERVAL -30 DAYS

But with that added, then the query won't return the "second latest" group if it's time is more than 30 days ago.

但是,如果添加了,那么如果时间超过30天,查询将不会返回“第二个最新”组。

The SELECT MAX(time) WHERE time < ( SELECT MAX(time) approach to get the second latest (the approach given in other answers) might be faster, especially if there is no index with leading column of time, but performance would best be gauged by actual testing. The index with leading column of time will speed up the MAX() approach as well.)

SELECT MAX(时间)WHERE时间<(SELECT MAX(时间)方法获得第二个最新值(其他答案中给出的方法)可能更快,特别是如果没有带有前导时间列的索引,但性能最好是通过实际测试来衡量。具有领先时间列的索引也将加速MAX()方法。)

The query I provided can be easily extended to get the 4th latest, 42nd latest, etc, by changing the LIMIT clause... LIMIT(3,1), LIMIT(41,1), etc.

我提供的查询可以通过更改LIMIT子句... LIMIT(3,1),LIMIT(41,1)等轻松扩展到第4个最新,第42个最新等。

#3


4  

This should give you second biggest time:

这应该给你第二大时间:

SELECT time FROM table GROUP BY time ORDER BY time DESC LIMIT 1,1

#4


1  

SELECT  T1.ITEM
FROM    YOURTABLE T1
WHERE   T1.TIME = ( SELECT  MAX(T2.TIME) 
                    FROM    YOURTABLE T2 
                    WHERE   T2.TIME < ( SELECT  MAX(T3.TIME) 
                                        FROM    YOURTABLE T3
                                    )
                )

#5


1  

Get second, third, fourth......Nth highest value using following query:

使用以下查询获取第二,第三,第四......第N个最高值:

SELECT MIN(value) from yourTable WHERE value IN( SELECT TOP N value FROM yourTable ORDER BY value DESC)

Replace N by you number i.e. N=2 for second highest value, N=3 for third highest value and so on. So for second highest value use:

用你的数字代替N,即第二个最高值N = 2,第三个最高值N = 3,依此类推。因此,对于第二高价值使用:

SELECT MIN(value) from yourTable WHERE value IN( SELECT TOP 2 value FROM yourTable ORDER BY value DESC)

#6


0  

Something really straightforward like this should work

像这样真正简单的东西应该有效

select * from my-table where time = 
  (Select top 1 time
     from (select top 2 time from my-table order by time desc)
   order by time asc)

#7


0  

Here is another solution which I think should work for your problem:

这是我认为应该适用于您的问题的另一个解决方案:

CREATE TEMPORARY TABLE xHighest AS (SELECT DISTINCT Time FROM `my-table` ORDER BY Time DESC LIMIT 1,1);

SELECT * FROM `my-table` JOIN xHighest ON (my-table.Time = xHighest.Time);

You can choose if second, third, ... highest value should be used by changing the first parameter of LIMIT.

您可以通过更改LIMIT的第一个参数来选择是否应使用第二个,第三个......最高值。

#8


0  

MYSQL: limit base solution

MYSQL:限制基础解决方案

Example: records 1, 2, 3, 4, 5.

示例:记录1,2,3,4,5。

LIMIT 2,1 means it will return 3rd highest number, as LIMIT 1,1 return 2nd highest number and so on

LIMIT 2,1意味着它将返回第3个最高数字,因为LIMIT 1,1返回第2个最高数字,依此类推

SELECT rc.rc_officer_id FROM recovery_complain_officer rc ORDER BY rc.rc_officer_id DESC LIMIT 2,1

SELECT rc.rc_officer_id FROM recovery_complain_officer rc ORDER BY rc.rc_officer_id DESC LIMIT 2,1

#9


0  

Leftfield-ish answer, but this allows you to select n-1 ordered values from a single table as you want (credit to the https://*.com/a/35234692/618320 answer by @Uueerdo), with nearly no extra cost.

Leftfield-ish答案,但这允许您根据需要从单个表中选择n-1个有序值(由@Uueerdo提供https://*.com/a/35234692/618320答案),几乎没有额外的成本。

You can use GROUP_CONCAT(DISTINCT...), followed by some SUBSTRING(...),

您可以使用GROUP_CONCAT(DISTINCT ...),然后使用一些SUBSTRING(...),

SELECT
  SUBSTRING_INDEX(groupTime, ',', 1) AS time1,
  SUBSTRING_INDEX(SUBSTRING_INDEX(groupTime, ',', 2), ',', -1) AS time2,
  SUBSTRING_INDEX(SUBSTRING_INDEX(groupTime, ',', 3), ',', -1) AS time3
FROM (
  SELECT GROUP_CONCAT(DISTINCT Time ORDER BY Time DESC) groupTime FROM mytable) t

The inner query would give you a single-row result back like "08-16-2013 00:00:00,08-13-2013 00:00:00,01-13-2012 00:00:00", and splitting that string up the way we are doing, gives you a table result like,

内部查询将为您提供单行结果,如“08-16-2013 00:00:00,08-13-2013 00:00:00,01-13-2012 00:00:00”,以及拆分串起我们的方式,给你一个表格结果,如,

time1                 time2                time3
---------             ------------         ------------
08-16-2013 00:00:00   08-13-2013 00:00:00  01-13-2012 00:00:00

#1


15  

You can try something like:

您可以尝试以下方法:

SELECT MAX(Time)
FROM yourTable
WHERE Time < (SELECT MAX(Time) FROM yourTable)

SQLFiddle Demo

SQLFiddle演示

#2


7  

One approach:

一种方法:

SELECT t.*
 FROM mytable t
 JOIN ( SELECT l.time
          FROM mytable l
         GROUP BY l.time
         ORDER BY l.time DESC
         LIMIT 1,1 
      ) m
   ON m.time = t.time

This uses an inline view (assigned an alias of m) to return the second "greatest" time value. The GROUP BY gets us a distinct list, the ORDER BY DESC puts the latest first, and the "trick" is the LIMIT, which returns the second row. LIMIT(m,n) = (skip first m rows, return next n rows)

这使用内联视图(指定别名为m)来返回第二个“最大”时间值。 GROUP BY为我们提供了一个独特的列表,ORDER BY DESC将最新的列表放在第一位,而“技巧”则是LIMIT,它返回第二行。 LIMIT(m,n)=(跳过前m行,返回n行)

With that time value, we can join back to the original table, to get all rows that have a matching time value.

使用该时间值,我们可以连接回原始表,以获得具有匹配时间值的所有行。


Performance will be enhanced with an index with leading column of time. (I think MySQL should be able to avoid a "Using filesort" operation, and get the result from the inline view query fairly quickly.)

使用具有领先时间列的索引将增强性能。 (我认为MySQL应该能够避免“使用filesort”操作,并且可以非常快速地从内联视图查询中获取结果。)

But, including a predicate in the inline view query, if you "know" that the second latest time will never be more than a certain number of days old, won't hurt performance:

但是,在内联视图查询中包含谓词,如果您“知道”第二个最新时间永远不会超过一定天数,则不会影响性能:

   WHERE l.time > NOW() + INTERVAL -30 DAYS

But with that added, then the query won't return the "second latest" group if it's time is more than 30 days ago.

但是,如果添加了,那么如果时间超过30天,查询将不会返回“第二个最新”组。

The SELECT MAX(time) WHERE time < ( SELECT MAX(time) approach to get the second latest (the approach given in other answers) might be faster, especially if there is no index with leading column of time, but performance would best be gauged by actual testing. The index with leading column of time will speed up the MAX() approach as well.)

SELECT MAX(时间)WHERE时间<(SELECT MAX(时间)方法获得第二个最新值(其他答案中给出的方法)可能更快,特别是如果没有带有前导时间列的索引,但性能最好是通过实际测试来衡量。具有领先时间列的索引也将加速MAX()方法。)

The query I provided can be easily extended to get the 4th latest, 42nd latest, etc, by changing the LIMIT clause... LIMIT(3,1), LIMIT(41,1), etc.

我提供的查询可以通过更改LIMIT子句... LIMIT(3,1),LIMIT(41,1)等轻松扩展到第4个最新,第42个最新等。

#3


4  

This should give you second biggest time:

这应该给你第二大时间:

SELECT time FROM table GROUP BY time ORDER BY time DESC LIMIT 1,1

#4


1  

SELECT  T1.ITEM
FROM    YOURTABLE T1
WHERE   T1.TIME = ( SELECT  MAX(T2.TIME) 
                    FROM    YOURTABLE T2 
                    WHERE   T2.TIME < ( SELECT  MAX(T3.TIME) 
                                        FROM    YOURTABLE T3
                                    )
                )

#5


1  

Get second, third, fourth......Nth highest value using following query:

使用以下查询获取第二,第三,第四......第N个最高值:

SELECT MIN(value) from yourTable WHERE value IN( SELECT TOP N value FROM yourTable ORDER BY value DESC)

Replace N by you number i.e. N=2 for second highest value, N=3 for third highest value and so on. So for second highest value use:

用你的数字代替N,即第二个最高值N = 2,第三个最高值N = 3,依此类推。因此,对于第二高价值使用:

SELECT MIN(value) from yourTable WHERE value IN( SELECT TOP 2 value FROM yourTable ORDER BY value DESC)

#6


0  

Something really straightforward like this should work

像这样真正简单的东西应该有效

select * from my-table where time = 
  (Select top 1 time
     from (select top 2 time from my-table order by time desc)
   order by time asc)

#7


0  

Here is another solution which I think should work for your problem:

这是我认为应该适用于您的问题的另一个解决方案:

CREATE TEMPORARY TABLE xHighest AS (SELECT DISTINCT Time FROM `my-table` ORDER BY Time DESC LIMIT 1,1);

SELECT * FROM `my-table` JOIN xHighest ON (my-table.Time = xHighest.Time);

You can choose if second, third, ... highest value should be used by changing the first parameter of LIMIT.

您可以通过更改LIMIT的第一个参数来选择是否应使用第二个,第三个......最高值。

#8


0  

MYSQL: limit base solution

MYSQL:限制基础解决方案

Example: records 1, 2, 3, 4, 5.

示例:记录1,2,3,4,5。

LIMIT 2,1 means it will return 3rd highest number, as LIMIT 1,1 return 2nd highest number and so on

LIMIT 2,1意味着它将返回第3个最高数字,因为LIMIT 1,1返回第2个最高数字,依此类推

SELECT rc.rc_officer_id FROM recovery_complain_officer rc ORDER BY rc.rc_officer_id DESC LIMIT 2,1

SELECT rc.rc_officer_id FROM recovery_complain_officer rc ORDER BY rc.rc_officer_id DESC LIMIT 2,1

#9


0  

Leftfield-ish answer, but this allows you to select n-1 ordered values from a single table as you want (credit to the https://*.com/a/35234692/618320 answer by @Uueerdo), with nearly no extra cost.

Leftfield-ish答案,但这允许您根据需要从单个表中选择n-1个有序值(由@Uueerdo提供https://*.com/a/35234692/618320答案),几乎没有额外的成本。

You can use GROUP_CONCAT(DISTINCT...), followed by some SUBSTRING(...),

您可以使用GROUP_CONCAT(DISTINCT ...),然后使用一些SUBSTRING(...),

SELECT
  SUBSTRING_INDEX(groupTime, ',', 1) AS time1,
  SUBSTRING_INDEX(SUBSTRING_INDEX(groupTime, ',', 2), ',', -1) AS time2,
  SUBSTRING_INDEX(SUBSTRING_INDEX(groupTime, ',', 3), ',', -1) AS time3
FROM (
  SELECT GROUP_CONCAT(DISTINCT Time ORDER BY Time DESC) groupTime FROM mytable) t

The inner query would give you a single-row result back like "08-16-2013 00:00:00,08-13-2013 00:00:00,01-13-2012 00:00:00", and splitting that string up the way we are doing, gives you a table result like,

内部查询将为您提供单行结果,如“08-16-2013 00:00:00,08-13-2013 00:00:00,01-13-2012 00:00:00”,以及拆分串起我们的方式,给你一个表格结果,如,

time1                 time2                time3
---------             ------------         ------------
08-16-2013 00:00:00   08-13-2013 00:00:00  01-13-2012 00:00:00