2012-04-22 12 views
19

Ich versuche, eine Teilmenge der Daten in einer Tabelle zu ordnen, aber ich denke, ich mache etwas falsch. Ich kann nicht viele Informationen über die Funktion rank() für Postgres finden, vielleicht suche ich an der falschen Stelle. So oder so:Wie in Postgres-Abfrage Rang

Ich möchte den Rang einer ID wissen, die in einem Cluster einer Tabelle basierend auf einem Datum fällt. Meine Frage lautet wie folgt:

select cluster_id,feed_id,pub_date,rank 
from (select feed_id,pub_date,cluster_id,rank() 
    over (order by pub_date asc) from url_info) 
as bar where cluster_id = 9876 and feed_id = 1234; 

ich diese Modellierung bin nach dem folgenden Stackoverflow Beitrag: postgres rank

Der Grund, warum ich denke, dass ich etwas falsch mache, ist, dass es nur 39 Zeilen in url_info, die in cluster_id 9876 und diese Abfrage wurde für 10 Minuten ausgeführt und kam nie zurück. (tatsächlich lief es für eine ganze Weile und es gab keine Ergebnisse, aber es gibt eine Zeile in Cluster 9876 für ID 1234) Ich erwarte, dass dies mir sagen wird, wie "ID 1234 war 5. für die Kriterien gegeben." Es nach meinen Anfragebeschränkungen einen relativen Rang zurück, oder?

Dies ist postgres 8.4 btw.

+3

Sie wollen den Rang relativ zu was? alle Datensätze (das ist, was Ihre Abfrage oben fragt und wahrscheinlich warum es zu lange dauert)? die Datensatzgruppe, die vom Prädikat ausgewählt wurde? eine andere Gruppierung? Die 'over'-Klausel sollte eine' Partition von' angeben, wenn Sie nicht über alle Zeilen ranken wollen. [Hier ist das Tutorial zu Fensterfunktionen] (http://www.postgresql.org/docs/8.4/static/tutorial-window.html) – dbenhur

+0

Ich möchte relativ zum pub_date ranken. Vielleicht kann ich es etwas besser erklären: url_info hat Tausende von URLs drin. 39 von ihnen kompilieren Cluster 9876. Indem Sie nur URLs auswählen, die Mitglied von 9876 sind (URL kann NUR Mitglied eines Clusters sein), möchte ich die URLs (die den Cluster 9876 bilden) in der Reihenfolge basierend auf pub_date einstufen.Benütze ich immer noch Partitionen, die auf Fensterfunktionen basieren? Ich schaute auf die URL, die Sie gesendet haben, und es sieht so aus, dass es sich auf Ranking-Artikel bezieht, nachdem ich einen Wert berechnet habe, den ich hier nicht tue. – WildBill

Antwort

26

durch den Rang() -Funktion in dem subselect platzieren und keine PARTITION BY in der über Klausel oder Prädikat Spezifizierungs In diesem Subselect fragt Ihre Abfrage nach einem Rang über die gesamte url_info-Tabelle, die von pub_date bestellt wurde.Das ist wahrscheinlich der Grund, warum es so lange lief, dass es über url_info rangierte, Pg muss die gesamte Tabelle nach pub_date sortieren, was ein während wenn die Tabelle sehr groß ist

Es scheint, dass Sie einen Rang nur für den Datensatzsatz generieren möchten, der von der WHERE-Klausel ausgewählt wird. In diesem Fall müssen Sie nur den Subselect eliminieren, und die RANK-Funktion steht implizit über der Menge der Datensätze, die diesem Prädikat entsprechen.

select 
    cluster_id 
,feed_id 
,pub_date 
,rank() over (order by pub_date asc) as rank 
from url_info 
where cluster_id = 9876 and feed_id = 1234; 

Wenn das, was Sie wirklich wollte, der Rang innerhalb des Clusters, unabhängig von der feed_id war, Sie in einem subselect Rang können, die diesem Cluster-Filter an:

select ranked.* 
from (
    select 
    cluster_id 
    ,feed_id 
    ,pub_date 
    ,rank() over (order by pub_date asc) as rank 
    from url_info 
    where cluster_id = 9876 
) as ranked 
where feed_id = 1234; 
+0

'rank() über (Auftrag von pub_date asc) als Rang ist redundant , da der Standardspaltenname der Name der Funktion ist – isapir

+0

@isapir Vielleicht so, aber das ist kein starkes Versprechen; aus der [docs] (https://www.postgresql.org/docs/current/static/sql-select.html#SQL-SELECT-LIST): "In komplexeren Fällen kann ein Funktions- oder Typenname ** sein * * verwendet, oder das System kann auf einen generierten Namen wie die Spalte? zurückgreifen? – dbenhur

5

ein weiteres Beispiel für DENSE_RANK Sharing() von PostgreSQL. Finden Sie Top-3-Studenten Beispiel Abfrage. Reference taken from this blog:

Erstellen Sie eine Tabelle mit Beispieldaten:

CREATE TABLE tbl_Students 
(
    StudID INT 
    ,StudName CHARACTER VARYING 
    ,TotalMark INT 
); 

INSERT INTO tbl_Students 
VALUES 
(1,'Anvesh',88),(2,'Neevan',78) 
,(3,'Roy',90),(4,'Mahi',88) 
,(5,'Maria',81),(6,'Jenny',90); 

Mit DENSE_RANK(), Berechnen RANK von Studenten:

;WITH cteStud AS 
(
    SELECT 
     StudName 
     ,Totalmark 
     ,DENSE_RANK() OVER (ORDER BY TotalMark DESC) AS StudRank 
    FROM tbl_Students 
) 
SELECT 
    StudName 
    ,Totalmark 
    ,StudRank 
FROM cteStud 
WHERE StudRank <= 3; 

Das Ergebnis:

studname | totalmark | studrank 
----------+-----------+---------- 
Roy  |  90 |  1 
Jenny |  90 |  1 
Anvesh |  88 |  2 
Mahi  |  88 |  2 
Maria |  81 |  3 
(5 rows)