3

我正在使用 SQL 查询

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

获得模态值,当然,这不是正确的,而是显示某些结果的第一选择。

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


使用 PostgreSQL 8.3+,我们可以使用这个用户定义的聚合来定义模式

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 与内置 AVG 函数进行比较)。 使用 PostgreSQL 9+,没有直接(内置)函数来计算统计模式值吗? 也许使用pg_stats...如何做类似的事情

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

pg_stats VIEW 可以用于这种任务(甚至一次,手动)

4

5 回答 5

10

从 PostgreSQL 9.4 开始,有一个内置的聚合函数mode。它像

SELECT mode() WITHIN GROUP (ORDER BY some_value) AS modal_value FROM tbl;

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

36.10.3。有序集聚合

内置有序集聚合函数

请参阅处理旧版本 Postgres 的其他答案。

于 2016-12-11T14:45:05.797 回答
1

If you want to do it by groups:

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
于 2013-04-25T12:15:58.767 回答
1

您可以尝试以下方法:

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

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

于 2013-04-24T11:23:29.187 回答
0

该模式具有最大的价值,所以我sobreescrevi我在这里找到的功能,我做了这个:

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
);
于 2014-10-21T13:07:18.863 回答
0

在问题介绍中,我用一个好的 SQL 编码解决方案引用了这个链接(@IgorRomanchenko 在这个答案中使用了相同的算法)。@ClodoaldoNeto 显示了一个“新解决方案”,但正如我评论的那样,它适用于标量和度量,而不是当前问题的答案。

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

结论

仅使用此页面和引用链接的信息(以及没有进一步信息的证据)得出结论。概括:

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

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


我在上下文中测试了引用的 SQL 聚合函数

SELECT mode(some_value) AS modal_value FROM t;

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

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

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

于 2013-06-19T03:05:25.003 回答