2016-10-27 3 views
-2

Я использую PostgreSQL и хочу использовать запрос, как это: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 

Это работает, но проблема в том, что занимает несколько минут, чтобы выполнить над большими объемами данных. Есть ли более быстрый способ, который может произойти за секунды? То, что я пытаюсь сделать, это взять только два элемента из строки, где оба значения сортируются в порядке возрастания.

id | device | value 

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

Выше мой стол (я знаю, что идентификаторы не являются уникальными, а не мой дизайн, но у него есть цель), но в пределах идентификатора позволяет говорить ID = 1, я хочу, чтобы выбрать идентификатор, устройство и значение самый маленький 2, поэтому мой результат будет 1, 123, 30 и 1, 456, 40 и т. д. для других идентификаторов.

Кроме того, если кто-нибудь знает, если вы вставляете отсортированные данные в базу данных, это гарантия для чтения в том же порядке?

+0

Что касается вашего первого вопроса: запустите 'EXPLAIN' (хотя он похоже, что вы пытаетесь сделать соединение). Что касается вашего второго вопроса: никогда не указывать '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

Try ниже запроса:

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

Это хорошо работает. Не думаю, что я понимаю, почему? И можно ли добавить еще один вид в идентификатор после сортировки значений? Кроме того, спасибо за то, что я не груб, я никогда не утверждал, что отлично разбираюсь в SQL и не умею писать. Как snark выше .... –

+0

Примите этот ответ, если с ним все в порядке. Что касается сортировки, то вы можете добавить любое количество столбцов в ваш заказ by clause после предложения, но убедитесь, что столбец также должен присутствовать в списке по столбцу. –

+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; 

Пример:

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) 

 Смежные вопросы

  • Нет связанных вопросов^_^