2015-05-02 3 views
2

Я пытаюсь создать статистику за значение для столбца в таблице, генерируя само значение, количество вхождений этого значения в таблицу и% от суммы из общей суммы ,Статистика по сравнению с таблицей в PostgreSQL

У меня есть таблица, например, как в следующем примере:

   Table "public.films" 
     Column |   Type   | Modifiers 
     --------+-----------------------+----------- 
     code | character(5)   | 
     title | character varying(40) | 


     # select * from films; 
     code | title 
     -------+------- 
     a1123 | yo1 
     a1124 | yo1 
     a1125 | yo2 
     a110 | yo3 
     a110v | yo3 
     a1a | yo3 
     a1az | yo3 
     (7 rows) 

Я попытался с помощью ранга() и percent_rank() для достижения этой цели, но это не сработало. Ожидаемый результат для приведенного выше примера будет:

 # select * from films; 
     title | title_count | title_percent 
     -------+-------------+------------------- 
     yo1 | 2   | 28% 
     yo2 | 1   | 14% 
     yo3 | 4   | 57% 

Что наиболее эффективный запрос для достижения этой цели, принимая во внимание, что таблица будет содержать более 100 миллионов значений? (Столбец индексируется)

ответ

1

Это должно помочь:

SELECT title, 
     COUNT(*) AS title_count, 
     ROUND(COUNT(*)/SUM(COUNT(*)) OVER() * 100) AS percent 
    FROM films 
GROUP 
    BY title 
ORDER 
    BY title 
+0

Спасибо, прост и работает! я надеюсь, что это не будет медленным для больших таблиц, принятым, поскольку все остальные ответы являются производными от этого – dispolito

0

Не уверен, что это наиболее эффективный запрос, хотя:

with total (total_count) as (
    select count(*)::numeric 
    from films 
) 
select title, 
     count(*) as title_count, 
     (count(*)::numeric/(select total_count from total)) * 100 as title_percent 
from films 
group by title 
order by title; 
0
SELECT title 
    ,title_count 
    ,(
     (
      title_count/(
       SELECT count(*)::NUMERIC 
       FROM films 
       ) 
      ) * 100 
     )::INT title_percent 
FROM (
    SELECT title 
     ,count(title)::NUMERIC title_count 
    FROM films 
    GROUP BY title 
    ORDER BY title 
    ) t; 

Результат:

title title_count title_percent 
----- ----------- ------------- 
yo1 2   29    
yo2 1   14    
yo3 4   57 

SELECT title 
    ,title_count 
    ,(
     (
      title_count/(
       SELECT count(*)::NUMERIC 
       FROM films 
       ) 
      ) * 100 
     )::INT::TEXT || '%' title_percent 
FROM (
    SELECT title 
     ,count(title)::NUMERIC title_count 
    FROM films 
    GROUP BY title 
    ORDER BY title 
    ) t; 

Результат:

title title_count title_percent 
----- ----------- ------------- 
yo3 4   57%   
yo1 2   29%   
yo2 1   14% 
1

И еще один один:

WITH code_cnt AS (
    SELECT title, count(*) AS title_count 
    FROM films 
    GROUP BY title), 
    gt AS (
    SELECT sum(title_count) AS grand_total 
    FROM code_cnt) 
SELECT title, title_count, (100 * title_count/grand_total) AS title_percent 
FROM code_cnt, gt 
ORDER BY title; 

Эта версия позволяет избежать использования count(*) на всю таблицу, которая является проблемой производительности, когда таблица велика. (Обратите внимание, что первые три ответа вычисляют как все записи во всей таблице, так и отдельно для каждой группы.)