PostgreSQL统计模式值

时间:2013-04-24 10:35:31

标签: postgresql statistics

我正在使用SQL查询

    SELECT round(avg(int_value)) AS modal_value FROM t;

获得modal value,这是不正确的,但是第一个显示某些结果的选项。

所以,我的问题是,“如何做正确的事情?”。


使用PostgreSQL 8.3+,我们可以使用this user-defined agregate 来定义模式

CREATE FUNCTION _final_mode(anyarray) RETURNS anyelement AS $f$
    SELECT a FROM unnest($1) a
    GROUP BY 1  ORDER BY COUNT(1) DESC, 1
    LIMIT 1;
$f$ LANGUAGE 'sql' IMMUTABLE;
CREATE AGGREGATE mode(anyelement) (
  SFUNC=array_append,  STYPE=anyarray,
  FINALFUNC=_final_mode, INITCOND='{}'
);

但是,作为用户定义的平均值,对于大表,它可能很慢(比较sum / count与buildin AVG函数)。 对于PostgreSQL 9+,没有用于计算统计模式值的直接(buildin)函数?也许使用pg_stats ... 如何做< / strong>类似

    SELECT (most_common_vals(int_value))[1] AS modal_value FROM t;

pg_stats VIEW可用于此类任务(甚至一次,手动)?

5 个答案:

答案 0 :(得分:4)

由于PostgreSQL 9.4有一个内置的聚合函数mode。它像

一样使用
SELECT mode() WITHIN GROUP (ORDER BY some_value) AS modal_value FROM tbl;

在此处阅读有关有序集合函数的更多信息:

36.10.3. Ordered-Set Aggregates

Built-in Ordered-Set Aggregate Functions

查看有关处理旧版Postgres的其他答案。

答案 1 :(得分:1)

您可以尝试以下内容:

SELECT int_value, count(*)
FROM t
GROUP BY int_value
ORDER BY count(*) DESC
LIMIT 1;

背后的想法 - 你得到每个int_value的计数,然后对它们进行排序(以便最大的count先行),然后LIMIT查询到第一行,仅获得最高计数的int_value

答案 2 :(得分:1)

如果您想按小组进行操作:

select
    int_value * 10 / (select max(int_value) from t) g,
    min(int_value) "from",
    max(int_value) "to",
    count(*) total
from t
group by 1
order by 4 desc

答案 3 :(得分:0)

在问题介绍中,我引用了this link一个很好的SQL编码解决方案(@IgorRomanchenko在这个答案中使用了相同的算法)。 @ClodoaldoNeto显示了一个“新解决方案”,但是我评论的是scalars and measures,而不是当前问题的答案。

粘贴了2个月和~40个视图,没有新问题 ...

Conlusions

仅使用此页面和引用链接的信息(以及缺乏进一步信息的证据)的结论。总结:

  1. 用户定义的聚合mode()就足够了,我们不需要内置(编译)版本。

  2. 没有优化的基础设施,内置的功能比用户定义的要好。


  3. 我在

    等语境中测试了cited SQL aggregate function
    SELECT mode(some_value) AS modal_value FROM t;
    

    而且,在我的测试中,它很快......所以,不能证明“内置函数”(如Oracle的STATS_MODE),只能在“统计包”需求上下文中 - 但如果你会花时间和记忆来安装我建议R language的东西。

    另一个隐含的问题是关于一个统计软件包“准备”或使用一些PostgreSQL基础设施(如pg_stats)... @IgorRomanchenko评论的“规范答案”的一个很好的线索:“pg_stat(...)仅包含估算值,而不包含确切的值”。因此,模式功能无法像我想象的那样利用基础设施。

    注意:我们必须记住,对于“模态间隔”,我们可以使用另一个函数,请参阅@ ClodoaldoNeto的答案。

答案 4 :(得分:0)

模式是最有价值的,所以我sobreescrevi我发现here的功能,我做了这个:

CREATE OR REPLACE FUNCTION _final_mode(anyarray)
  RETURNS anyelement AS
    $BODY$
    SELECT 
        CASE 
            WHEN t1.cnt <> t2.cnt THEN t1.a 
            ELSE NULL 
        END
        FROM
            (SELECT a, COUNT(*) AS cnt
             FROM unnest($1) a
             WHERE a IS NOT NULL
             GROUP BY 1 
             ORDER BY COUNT(*) DESC, 1
             LIMIT 1
            ) as t1, 
            (SELECT a,
             COUNT(*) AS cnt
             FROM unnest($1) a
             WHERE a IS NOT NULL
             GROUP BY 1 
             ORDER BY COUNT(*) DESC, 1
             LIMIT 2 OFFSET 1
            ) as t2
    $BODY$
LANGUAGE 'sql' IMMUTABLE;

-- Tell Postgres how to use our aggregate
CREATE AGGREGATE mode(anyelement) (
  SFUNC=array_append, --Function to call for each row. Just builds the array
  STYPE=anyarray,
  FINALFUNC=_final_mode, --Function to call after everything has been added to array
  INITCOND='{}' --Initialize an empty array when starting
);