2016-10-27 7 views
-2

SQLスピードの問題

SELECT device, value, id 
FROM myTable s 
WHERE (SELECT COUNT(*) FROM myTable f WHERE f.id = s.id AND f.value >= s.value) <= 2 

これは動作しますが、問題は、それが大規模なデータをオーバー実行するのに数分かかります。数秒で起こるより速い方法がありますか?私がしようとしているのは、両方の値が昇順でソートされている行から2つの項目だけを取ることです。

id | device | value 

1  123  40 
1  456  30 
1  789  45 
2  12  10 
2  11  9 

以上が私のテーブルです(私はない私のデザイン、IDは一意ではありません知っているが、それは目的を持っている)ですが、id内のid = 1を言うことができます、私は、ID、デバイスとの値を選択します最小2なので、私の結果は1、123、30、1、456、40などとなります。

また、誰かが知っていれば、ソートしたデータをデータベースに挿入すれば、同じ順序で読み返すことができますか?クエリ以下

+0

あなたの最初の質問についてあなたが参加しようとしているように見えます)。あなたの2番目の質問について:いつも "ORDER BY" – PeeHaa

+4

"*ソートされたデータをデータベースに挿入すると、同じ順序で読み返すことが保証されます*"と指定する必要はありません。クエリで 'order by 'を使用していない限り、データベースは行を返す順序を自由に選択できます。 –

+0

特に、適切なインデックスが利用できない場合、相関サブクエリは避けます(' id' 'value'を先頭の列としています)。各行の「最高値」を持つ行を探していたら、恐らく**' dense_rank' **のようなウィンドウ関数を使用します。参照:https://www.postgresql.org/docs/9.5/static/functions-window.html(まったく同じ質問は見つけられませんか?)結果が特定の順序で返されるようにするには、 ORDER BY'節。 – spencer7593

答えて

2

試してみてください。

SELECT s.device,s.id,s.value 
FROM myTable s 
INNER JOIN myTable f ON s.id = f. id AND f.value >= s.value 
GROUP BY s.device,s.id,s.value 
HAVING COUNT(s.id) <= 2 
+0

これはかなりうまくいきます。なぜ私はかなり理解しているとは思わない?そして、値のソート後にidにもう1つのソートを追加することは可能ですか?また、無礼ではないことに感謝し、私はSQLや偉大な作家に偉大であるとは決して言わなかった。上のsnarkのように.... –

+0

あなたはそれで大丈夫ならこの答えを受け入れてください。並べ替えが問題になる限り、句を指定した後、by節で任意の数の列を追加することができますが、列が列リストにグループ化されている必要があります。 –

+0

私は公式の答えとして受け入れることができるようになるとすぐに、私は感謝しています。私の推測では、内部結合のために実行が速くなっていますか? –

-1

これは、ウィンドウ関数を使用して行うことができます。

select id, device, value 
from (
    select id, device, value, 
     row_number() over (partition by id order by value) as rn 
    from the_table 
) t 
where rn <= 2 
order by id, device, value; 

例:それものの、実行 `EXPLAIN`(:

postgres> create table the_table (id integer, device integer, value integer); 
CREATE TABLE 
postgres> insert into the_table values 
...> (1, 123, 40), 
...> (1, 456, 30), 
...> (1, 789, 45), 
...> (2, 12 , 10), 
...> (2, 11 , 9); 
INSERT 0 5 

postgres> select id, device, value 
...> from (
...> select id, device, value, 
...>   row_number() over (partition by id order by value) as rn 
...> from the_table 
...>) t 
...> where rn <= 2; 

id | device | value 
----+--------+------- 
    1 | 123 | 40 
    1 | 456 | 30 
    2 |  11 |  9 
    2 |  12 | 10 
(4 rows)