2016-10-27 7 views
-2

Ich bin mit PostgreSQL und eine Abfrage wie diese verwenden möchten:SQL Geschwindigkeit Ausgabe

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

Dies funktioniert, aber das Problem ist es Minuten dauert große Daten auszuführen über. Gibt es einen schnelleren Weg, der in Sekunden passieren kann? Was ich versuche zu tun, ist nur zwei Elemente aus einer Zeile, wo beide Werte in Asc Reihenfolge sortiert sind.

id | device | value 

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

die oben ist mein Tisch (ich weiß ids nicht eindeutig zuzuordnen ist, nicht meine Absicht, aber es hat einen Zweck), aber innerhalb der ID kann sagen id = 1, ich will id, Gerät und Wert auszuwählen von die kleinste 2, so würde mein Ergebnis 1, 123, 30 und 1, 456, 40 usw. für andere IDs sein.

Auch wenn jemand weiß, wenn Sie sortierte Daten in eine Datenbank einfügen, ist es eine Garantie, in der gleichen Reihenfolge wieder zu lesen?

+0

In Bezug auf Ihre erste Frage: run 'EXPLAIN' (obwohl es sieht so aus als ob du versuchst mitzumachen). Zu Ihrer zweiten Frage: no geben Sie immer 'ORDER BY' an. – PeeHaa

+4

* * Wenn Sie sortierte Daten in eine Datenbank einfügen, ist es eine Garantie, in der gleichen Reihenfolge zurückzulesen *" Das ist ein klares: ** NEIN **. Wenn Sie in Ihrer Anfrage keine 'order by' verwenden, kann die Datenbank jede Reihenfolge frei wählen, in der die Zeilen zurückgegeben werden sollen. –

+0

Ich würde eine korrelierte Unterabfrage vermeiden, besonders wenn ein passender Index nicht verfügbar ist (mit' id' und "Wert" als die führenden Spalten in dieser Reihenfolge. Wenn ich nach den Zeilen mit den "höchsten zwei Werten" für jede Zeile suchen würde, würde ich wahrscheinlich eine Fensterfunktion verwenden, wie ** 'dicht_Rank' **. Siehe: https://www.postgresql.org/docs/9.5/static/functions-window.html (Könnten Sie ernsthaft * keine * ähnlichen Fragen finden?) Wenn Sie möchten, dass ein Ergebnis in einer bestimmten Reihenfolge zurückgegeben wird, fügen Sie ein 'hinzu ORDER BY-Klausel. – spencer7593

Antwort

2

Versuchen unter Abfrage:

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

Das funktioniert ganz gut, danke. Ich glaube nicht, ich verstehe warum? Und ist es möglich, eine weitere Sortierung der ID nach der Wert Sortierung hinzuzufügen? Außerdem, danke, dass ich nicht unhöflich war, behauptete ich nie, dass ich in SQL großartig wäre oder ein großer Autor. Wie der Snark oben .... –

+0

Bitte akzeptieren Sie diese Antwort, wenn Sie damit einverstanden sind. Was die Sortierung betrifft, können Sie eine beliebige Anzahl von Spalten in der Reihenfolge nach der Klausel hinzufügen, aber stellen Sie sicher, dass die Spalte auch in der Gruppe nach Spaltenliste vorhanden sein muss. –

+0

Ich bin dankbar, sobald es mich lässt, werde ich als offizielle Antwort akzeptieren. Meine Vermutung ist, dass es wegen der inneren Verbindung schneller läuft? –

-1

Dies kann Funktionen Fenster erfolgen:

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; 

Beispiel:

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)