2012-04-22 11 views
19

Sto provando a classificare un sottoinsieme di dati all'interno di una tabella ma penso di fare qualcosa di sbagliato. Non riesco a trovare molte informazioni sulla funzione rank() per postgres, forse sto cercando nel posto sbagliato. In entrambi i casi:Come classificare la query postgres

Mi piacerebbe conoscere il grado di un ID che rientra in un cluster di una tabella in base a una data. La mia domanda è la seguente:

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; 

sto modellando questo dopo il seguente post StackOverflow: postgres rank

Il motivo penso che sto facendo qualcosa di sbagliato è che ci sono solo 39 righe in url_info che sono cluster_id 9876 e questa query ha funzionato per 10 minuti e non è mai tornata indietro. (in realtà l'ho ripubblicato per un po 'e non ha restituito risultati, eppure c'è una riga nel cluster 9876 per l'ID 1234) Mi aspetto che questo mi dica qualcosa del tipo "id 1234 era 5 per i criteri forniti). restituirà un rango rispetto secondo i miei vincoli di query, giusto?

Questo è Postgres 8.4 btw.

+3

Vuoi il rango relativo a cosa? tutti i record (questo è ciò che la tua query sopra chiede e probabilmente perché ci vuole troppo tempo)? l'insieme di record selezionati dal predicato? qualche altro raggruppamento? La clausola 'over' dovrebbe specificare una' partition by' se non si vuole classificare su tutte le righe. [Ecco il tutorial sulle funzioni della finestra] (http://www.postgresql.org/docs/8.4/static/tutorial-window.html) – dbenhur

+0

Voglio classificarmi rispetto al pub_date. Forse posso spiegare un po 'meglio: url_info contiene migliaia di URL. 39 di loro compse cluster 9876. Selezionando solo url che sono un membro di 9876 (l'URL può SOLO essere membro di un cluster), voglio classificare l'url (che compongono il cluster 9876) in base a pub_date.Continuo a utilizzare partizioni basate su funzioni di finestra per questo? Ho guardato l'URL che hai inviato e sembra che questo si riferisca a elementi di ranking dopo aver calcolato un valore, che non sto facendo qui .... – WildBill

risposta

26

ponendo la funzione di rango() nella subselect e non specificando una partizione nella clausola sopra o qualsiasi predicato in quella sottoselezione, la tua query ti chiede di produrre un rank sull'intera tabella url_info ordinata per pub_date. Questo è probabilmente il motivo per cui è scaduto fino a classificare su url_info, Pg deve ordinare l'intera tabella per pub_date, che prenderà un mentre se il tavolo è molto grande

Sembra che si desideri generare una classifica solo per l'insieme di record selezionati dalla clausola where, nel qual caso tutto ciò che occorre fare è eliminare la sottoselezione e la funzione di classifica è implicitamente sull'insieme di record corrispondenti a tale predicato.

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; 

Se quello che realmente voleva era il rango all'interno del cluster, indipendentemente dal feed_id, si può classificare in una selezione secondaria che filtra a tale cluster:

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() over (ordine di pub_date asc) come rank' è ridondante , poiché il nome della colonna di default è il nome della funzione – isapir

+0

@isapir Forse sì, ma questa non è una promessa forte; da [docs] (https://www.postgresql.org/docs/current/static/sql-select.html#SQL-SELECT-LIST): "In casi più complessi, un nome di funzione o tipo ** potrebbe essere * * usato, o il sistema può ricorrere a un nome generato come? colonna? " – dbenhur

5

Condivisione altro esempio di DENSE_RANK() di PostgreSQL. Trova la query di esempio tra i primi 3 studenti. Reference taken from this blog:

Creare una tabella con dati di esempio:

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

Utilizzando DENSE_RANK(), calcolare RANK di studenti:

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

Il Risultato:

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