PostgreSQL-返回表中所有列的最常用值

PostgreSQL-返回表中所有列的最常用值,postgresql,Postgresql,我有一个包含很多列的表,我想运行一个查询来查找每列中最常见的值 通常对于单个专栏,我会运行以下内容: SELECT country FROM users GROUP BY country ORDER BY count(*) DESC LIMIT 1 PostgreSQL是否有一个内置函数来执行此操作,或者有人能建议我运行一个查询来实现此操作吗?如果我正在执行此操作,我会编写一个如下查询: SELECT 'country', country FROM users GROUP BY country

我有一个包含很多列的表,我想运行一个查询来查找每列中最常见的值

通常对于单个专栏,我会运行以下内容:

SELECT country
FROM users
GROUP BY country
ORDER BY count(*) DESC
LIMIT 1

PostgreSQL是否有一个内置函数来执行此操作,或者有人能建议我运行一个查询来实现此操作吗?

如果我正在执行此操作,我会编写一个如下查询:

SELECT 'country', country
FROM users
GROUP BY country
ORDER BY count(*) DESC
LIMIT 1
UNION ALL
SELECT 'city', city
FROM USERS
GROUP BY city
ORDER BY count(*) DESC
LIMIT 1
-- etc.

应该注意的是,只有当所有列都是兼容类型时,这才有效。如果不是,您可能需要不同的解决方案。

使用相同的查询,对于多个列,您应该执行以下操作:

SELECT *
FROM
(
    SELECT country
    FROM users
    GROUP BY 1
    ORDER BY count(*) DESC
    LIMIT 1
) country
,(
    SELECT city
    FROM users
    GROUP BY 1
    ORDER BY count(*) DESC
    LIMIT 1
) city
这适用于任何类型,并将返回同一行中的所有值,列具有其原始名称

对于更多列,只是有更多子查询,如下所示:

,(
    SELECT someOtherColumn
    FROM users
    GROUP BY 1
    ORDER BY count(*) DESC
    LIMIT 1
) someOtherColumn
编辑:


您还可以使用窗口功能访问它。但是,它的性能和可读性都不会更好。

此窗口函数版本将分别读取用户表和计算表一次。相关子查询版本将为每个列读取一次用户表。如果列数与OPs中的列数相同,那么我猜这会更快


从第9.4页开始,有一个聚合函数:

mode() WITHIN GROUP (ORDER BY sort_expression)
返回最频繁的输入值(如果有多个相同频率的结果,可任意选择第一个)

对于早期版本,您可以创建一个

  CREATE OR REPLACE FUNCTION mode_array(anyarray)
            RETURNS anyelement AS
$BODY$
    SELECT a FROM unnest($1) a GROUP BY 1 ORDER BY COUNT(1) DESC, 1 LIMIT 1;
$BODY$
LANGUAGE SQL IMMUTABLE;



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

用法:
从表中选择模式(列)

查询出了什么问题?@Denis:OP想要得到每一列的模式,而不仅仅是
国家
列。不过,我不确定这是否有特别的关系。@Keven:啊,是的,它开始起作用了。OP可能应该查看窗口函数。另一种方法是在正确分析表格后,使用
pg_stats
中的
最常用值。不要认为使用窗口函数可以更容易地实现。每列至少需要一个计数(*)或
。因此,最好坚持使用简单易读的SQL。检查我的回答你的回答很好,正如你所说的,所有数据都在同一列中,类型相同,但是我不认为这是被问到的。这更好,更接近OP想要的。你能告诉我这些逗号分隔的子查询的使用是在哪里记录的吗?我想了解更多。逗号分隔的是笛卡尔积,我认为它属于SQL标准。FROM子句的基本用法是:您能提供
EXPLAIN
结果来支持该断言吗?@Kevin它不是一个断言。这只是猜测。你会构建数据吗?在我看来,查询计划器应该能够(部分)优化重复的子查询。我只是好奇事实是否如此。您不需要大量数据来查看它是否正在进行20层深度的嵌套迭代。从本例中不清楚,但是在GROUP(ORDER BY*sort\u expression*)
中调用
mode(),
故意不向
mode
函数发送参数。e、 g.聚合函数的正确用法应该是组内的
mode()(按col\u name DESC排序),这是最常见的条目
@BrDaHa,您可能希望写入PostgreSQL支持,因为这是他们文档中的一个示例
  CREATE OR REPLACE FUNCTION mode_array(anyarray)
            RETURNS anyelement AS
$BODY$
    SELECT a FROM unnest($1) a GROUP BY 1 ORDER BY COUNT(1) DESC, 1 LIMIT 1;
$BODY$
LANGUAGE SQL IMMUTABLE;



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