在类似值的情况下获得第1和第2高的vlaue行

时间:2017-10-26 16:13:13

标签: mysql max

我有一个包含列的表:id,status,value。

id    status    value
--    ------    -----
1       10       100
2       10       100
3       10        60
4       11        20
5       11        15
6       12       100
7       12        50
8       12        50  

我想从每个状态组中获取第一个和第二个最高值的行的id和值。我的表应该有以下列:
status,第一个最高值的id,第一个最高值,第二个最高值的id,第二个最高值。

我应该得到:

status  1stID  1stValue  2ndID  2ndValue
------  -----  --------  -----  --------
  10     1/2      100     2/1      100
  11      4       20       5       15
  12      6      100      7/8      50   

我尝试了各种解决方案,但我找不到相同值的第一个解决方案(两个具有相同值的行,这恰好是该状态组中的最高值)或相同值秒。

例如,如果两行在其状态组中共享最高值,则这个不太优雅的查询将返回两行具有相同的状态,不同的1和相同的第二行:

    SELECT 2nds.status, 1sts.id AS "1stID",1sts.value AS "1stValue",
 2nds.id AS "2ndID",2nds.value AS "2ndValue" 
FROM    
    (SELECT v.* FROM 
    (SELECT status, MAX(value) AS "SecMaxValue" FROM table o
    WHERE value  < (SELECT MAX(value) FROM table 
                   WHERE status = o.status
                   GROUP BY status) AS m
    INNER JOIN table v
    ON v.status = m.status AND v.value = m.SecMaxValue) AS 2nds

    INNER JOIN

    (SELECT v.* FROM 
    (SELECT status, MAX(value) AS maxValue FROM table
    GROUP BY status) AS m
    INNER JOIN table v
    ON v.status = m.status AND v.value = m.MaxValue) AS 1sts    
    ON 1sts.status = 2nds.status ;

这个查询会给我:

status  1stID  1stValue  2ndID  2ndValue
------  -----  --------  -----  --------
  10      1      100       3       60
  10      2      100       3       60
  11      4       20       5       15
  12      6      100       7       50
  12      6      100       8       50     

总而言之,我想找到一个解决方案,其中: 一个。如果有两行具有最高值,则查询将其中一个详细信息放在第1列中,其他详细信息放在第2列中(无其他) 湾如果有两行具有第二个最高值,则它将最高位置放在第二位。

有没有办法更改上面的查询?有人有更好的解决方案吗?

  • 我遇到了几个第一和第二个查询,但他们遇到了同样的问题 - 例如此解决方案:Finding the highest n values of each group in MySQL。它不会在同一行中提供第一和第二,但主要问题是它只提供了一个第一。

由于

1 个答案:

答案 0 :(得分:2)

花了很多时间后,我终于找到了解决上述问题的方法。请试一试:

    select 1st.status as Status,
       SUBSTRING_INDEX(1st.id,'/',1) as 1stID,
       1st.value as 1stValue,
       (case when locate('/',1st.id) > 0 then SUBSTRING_INDEX(1st.id,'/',-1)
             else 2nd.id 
        end) as 2ndID,
        (case when locate('/',1st.id) > 0 then 1st.value
             else 2nd.value 
        end) as 2ndValue
        from
(
(select status, SUBSTRING_INDEX(Group_concat(id separator '/'),'/',2) as id,value
from t1
where (status,value) in (select status,value
from t1
group by status
having max(value))
group by status) 1st

inner join

(select status,id,value
from t1
where (status,value) not in (select status,value
from t1
group by status
having max(value))
group by status,value
order by status,value desc) 2nd
on 1st.status = 2nd.status)
group by 1st.status;

只需将t1替换为您的表名,它应该像魅力一样。

Click here for Updated Demo

如果您有任何疑问,请随时提出。

希望它有所帮助!