如何为每个Y找到最相关的X?

时间:2014-03-27 01:19:21

标签: sql postgresql aggregate-functions greatest-n-per-group

我有一个可以运行的查询,它生成如下行:

 ID | category | property_A | property_B
----+----------+------------+------------
  1 |        X |       tall |        old
  2 |        X |      short |        old
  3 |        X |       tall |        old
  4 |        X |      short |      young
  5 |        Y |      short |        old
  6 |        Y |      short |        old
  7 |        Y |       tall |        old

我想为每个categoryproperty_B找到最常见的property_A,然后将其放入另一个表格供以后使用。所以在这里我想知道,在X类中,老年人往往很高,年轻人很矮,而在Y类,老年人往往很矮。

每列的域都是有限的,而且不是太大 - 有200个类别,还有十几个属性_A和property_B。所以我可以在我的客户端上编写一个愚蠢的脚本,它会查询数据库200 * 12 * 12次,进行有限的查询,但这看起来一定是错误的方法,而且浪费,因为生成这个表是很昂贵的然后扔掉大部分。

但我甚至不知道要查找哪些单词以找到正确的方法:“sql find related rows”显示了如何查找整数相关性,但我对整数不感兴趣。那我该怎么做呢?

2 个答案:

答案 0 :(得分:3)

您可以通过聚合和窗口/分析功能轻松完成此操作。你想要排名第一的人数。以下返回最受欢迎的A:

select category, property_b, property_a as MostPopularA
from (select category, property_b, property_a, count(*) as cnt,
             row_number() over (partition by category, property_b order by count(*) desc) as seqnum
      from table t
      group by category, property_b, property_a
     ) t
where seqnum = 1;

如果您想在有平局时获取所有值,请使用dense_rank()代替row_number()

答案 1 :(得分:2)

我建议使用GROUP BYDISTINCT ON的组合,这在Postgres中更快/更简单/更优雅:

SELECT DISTINCT ON (category, property_b)
       category, property_b, property_a, count(*) AS ct
FROM   tbl
GROUP  BY category, property_b, property_a
ORDER  BY category, property_b, ct DESC;

返回:

category | property_b | property_a | ct
---------+------------+------------+----
X        | old        | tall       | 2
X        | young      | short      | 1
Y        | old        | short      | 2

如果多个对等体绑定最常见的值,则只返回一个任意选择。

这适用于没有子查询的单个查询级别,因为在GROUP BY步骤之前应用了聚合(DISTINCT)。 DISTINCT ON的详细说明:
Select first row in each GROUP BY group?

SQL Fiddle.