2012-04-22 10 views
19

Estoy tratando de clasificar un subconjunto de datos dentro de una tabla, pero creo que estoy haciendo algo mal. No puedo encontrar mucha información sobre la función de rango() para postgres, tal vez estoy buscando en el lugar equivocado. De cualquier forma:Cómo clasificarse en la consulta de postgres

Me gustaría saber el rango de una identificación que se encuentra dentro de un clúster de una tabla basada en una fecha. Mi consulta es la siguiente:

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; 

estoy modelando esto después del siguiente post StackOverflow: postgres rank

La razón creo que estoy haciendo algo mal es que sólo hay 39 filas en url_info que se encuentran en cluster_id 9876 y esta consulta se ejecutó durante 10 minutos y nunca volvió. (en realidad lo volvieron a ejecutar durante bastante tiempo y no devolvió ningún resultado, sin embargo, hay una fila en el clúster 9876 para el ID 1234). Espero que esto me diga algo así como "id 1234 fue el quinto para los criterios dados". devolverá un rango relativo de acuerdo con mis restricciones de consulta, correctos?

Ésta es Postgres 8.4 por cierto.

+3

¿Quieres el rango relativo a qué? todos los registros (esto es lo que pregunta su consulta anterior y probablemente ¿por qué tarda demasiado?) el conjunto de registros seleccionados por el predicado? alguna otra agrupación? La cláusula 'over' debe especificar una' partition by' si no desea clasificar todas las filas. [Aquí está el tutorial sobre las funciones de la ventana] (http://www.postgresql.org/docs/8.4/static/tutorial-window.html) – dbenhur

+0

Quiero clasificar en relación con el pub_date. Quizás pueda explicarlo un poco mejor: url_info tiene miles de URL. 39 de ellos compse cluster 9876. Al seleccionar solo url's que son miembros de 9876 (la url solo puede ser miembro de un clúster), quiero clasificar las url (que componen el clúster 9876) en orden basado en pub_date.¿Todavía uso particiones basadas en funciones de ventana para esto? Miré la URL que enviaste y parece que esto se refiere a los elementos de clasificación después de que calculo algún valor, que no estoy haciendo aquí ... – WildBill

Respuesta

26

colocando la función rANK() en la subselección y no especifica una partición en la cláusula sobre o cualquier predicado En esa subselección, su consulta está pidiendo que se genere un rango en toda la tabla url_info ordenada por pub_date. Es probable que esto haya dado como resultado clasificar a todo url_info, Pg debe ordenar toda la tabla por pub_date, lo que tomará una mientras que si la tabla es muy grande

Parece que desea generar un rango solo para el conjunto de registros seleccionados por la cláusula where, en cuyo caso, todo lo que necesita hacer es eliminar la subselección y la función de rango está implícitamente sobre el conjunto de registros que coinciden con ese predicado.

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; 

Si lo que realmente quería era el rango dentro del grupo, independientemente de la FEED_ID, puede clasificar en una subselección que filtra a ese grupo:

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() más (orden por pub_date asc) como rank' es redundante , como el nombre predeterminado de la columna es el nombre de la función – isapir

+0

@isapir Quizás sea así, pero esa no es una gran promesa; de [docs] (https://www.postgresql.org/docs/current/static/sql-select.html#SQL-SELECT-LIST): "En casos más complejos, una función o tipo de nombre ** puede ser * * utilizado, o el sistema puede recurrir a un nombre generado, como? column? " – dbenhur

5

compartir otro ejemplo de DENSE_RANK() de PostgreSQL. Encuentra la consulta de muestra de los 3 mejores estudiantes. Reference taken from this blog:

Crear una tabla con datos de ejemplo:

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

Usando DENSE_RANK(), Calcular rango de estudiantes:

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

El resultado:

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