2017-10-26 11 views
2

ID、ステータス、値の列を持つテーブルがあります。類似の値の場合は、1番目と2番目に高いvlaue行を取得します。

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 

各ステータスグループから1番目と2番目に高い値の行のIDと値を取得したいと考えています。私のテーブルは、次の列を持つ必要があります:
ステータス、最初の最高値のID、最初の最高値、2番目に高い値のID、2番目に高い値。

私が取得する必要があります。

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

私はソリューションのすべての種類を試してみましたが、私は最高であることを起こっ同じ値第一S(同じ値を持つ2つの列のための解決策を見つけることができませんでしたそのステータスグループの)または同じ値の秒。

例えば、そのステータス群で最高値を共有する二列の場合には、このそれほどエレガントクエリが同じ状態、異なる1stsと同じ第2の2つの行を返すであろう。

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  

を締結するために、私はここで解決策を見つけるしたいと思います: 。最も高い値を持つ2つの行がある場合、クエリは1番目の列に詳細情報の1つを入れ、2番目に他の詳細情報(マザーなし) b。 2番目の高い値を持つ2つの行がある場合は、最も高い値をその場所に置き、1つを2番目の場所に置きます。

上記のクエリを変更する方法はありますか?誰かがより良い解決策を持っていますか?

  • いくつかの第1および第2のクエリが出てきましたが、同じ問題が発生しました。たとえば、この解決策はFinding the highest n values of each group in MySQLです。それは同じ行で1位と2位を提供しませんが、主な問題は最初のものの1つだけです。

多くの時間を費やした後おかげ

+2

サンプルデータ、現在の結果および希望する結果を適切な形式で入力してください。本当に役に立ちます。 –

+2

MySQL 8.0にアップグレードすると、この種の問題はとても簡単になります。 [RANK()ウィンドウ関数](https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_rank)を使用してください。 –

+0

@BillKarwin情報ありがとうございました。私は 'rank()'と 'dense_rank()'がMySQLでも導入されていることに気づいていませんでした。もちろん、これらの機能によって、このタスクはそれより簡単になります。 –

答えて

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; 

ちょうどあなたのtablenameで置き換えると、それは魅力的に動作するはずです。

Click here for Updated Demo

あなたは何の疑い(複数可)をお持ちの場合は、お気軽に。

希望すると助かります!

+0

ありがとうHarshil!デモのクエリは上記のクエリとは異なります。上記のクエリを実行すると、何らかの理由で期待される1と2の最初の行に10が入ります。デモのクエリは実際に素晴らしい作品です。私は申し訳ありませんが、おそらく私は十分に私の質問では明確ではなかった - 私はdid'ntテーブルが同じセル内の第一と第二のIDの両方を提示することを意味しません。私は文字列を置くつもりはなかった。私はid 1 OR id 2を右下のセルid 6またはid 7に入れることを意図していました。文字列から切り捨てて整数に戻すことはできますが、複雑すぎることはありませんか?努力のために再びありがとう! – Elon

+0

したがって、ステータス1の1stIDと2ndIDとして1または2を表示したいですか?そうですか? –

+0

はい、1を2より大きく表示すると2を表示し、逆も同様です。ああ、私はあなたがデモで10を追加したことに気づきました。間違いなく、どちらも素晴らしい作品です。その場合、1番目のidは1,2,10のいずれかになります。 2つ目は残りの2つのうちの1つになります。 – Elon

関連する問題