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

时间:2014-12-18 15:48:57

标签: postgresql

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

通常对于一个列,我会运行类似:

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

PostgreSQL是否有内置函数来执行此操作,或者任何人都可以建议我可以运行的查询来实现此目的吗?

4 个答案:

答案 0 :(得分:3)

使用相同的查询,您应该执行多个列:

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

这适用于任何类型,并将返回同一行中的所有值,并且列具有其原始名称。

对于更多列,只有更多的subquerys:

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

修改:

您也可以通过窗口功能与它联系。然而,它在性能和可读性方面都不会更好。

答案 1 :(得分:1)

如果我这样做,我会写一个像这样的查询:

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.

应该注意,这只适用于所有列都是兼容类型的情况。如果不是,您可能需要一个不同的解决方案。

答案 2 :(得分:1)

此窗口函数版本将分别读取users表和计算表。相关子查询版本将为每个列读取一次users表。如果在OPs情况下列很多,那么我的猜测是这更快。 SQL Fiddle

select distinct on (country_count, age_count) *
from (
    select
        country,
        count(*) over(partition by country) as country_count,
        age,
        count(*) over(partition by age) as age_count
    from users
) s
order by country_count desc, age_count desc
limit 1

答案 3 :(得分:1)

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

用法:SELECT mode(column) FROM table;