postgresql 如何从一列中获取另一列中某个值的cume_dist(或百分位数)?

pvcm50d1  于 2023-03-08  发布在  PostgreSQL
关注(0)|答案(1)|浏览(161)

我在DBT中使用postgresql,所以postgresql或DBT解决方案都是可行的。
我有一个基本上包含4列的表target, question, value, current
我可以用下式得到该值的百分位数(cume_dist):

(cume_dist() over (partition by question order by value)) * 100 as percentile

但是,当前值为零的目标不在比较中,我需要它们的百分比,但它们不在“数据集”中(它们是来自相同目标的历史数据,因此它们不是当前值,但我需要百分比,就好像它们是当前值一样)
但是,我实际上需要current为1的值子集中每个值的百分位数。
ETA:我在文档中看到cume_dist可以接受参数,但是我没有找到任何关于这些参数代表什么或者如何使用它们的文档...

42fyovps

42fyovps1#

重新实现cume_dist()

据我所知,用现有的cume_dist()函数无法做到这一点,但不用cume_dist()实现相同的functionalify是相当容易的。
postgres docs表示cume_dist()
返回累积分布,即(当前行之前的分区行数或与当前行对等的分区行数)/(分区总行数)。因此,该值的范围从1/N到1。
下面是我如何设置我的演示数据:

CREATE TABLE my_table (
  target VARCHAR,
  question VARCHAR,
  value INT,
  current BOOL
);

INSERT INTO my_table VALUES
('alice',   'number of hats', 7, true),
('alice',   'number of hats', 6, false),
('alice',   'number of hats', 3, false),
('bob',     'number of hats', 4, true),
('charles', 'number of hats', 9, true),
('david',   'number of hats', 0, true),
('erin',    'number of hats', 4, true),
('alice',   'number of fingers', 10, true),
('bob',     'number of fingers', 10, true),
('charles', 'number of fingers',  9, true),
('charles', 'number of fingers', 10, false),
('david',   'number of fingers', 10, true),
('erin',    'number of fingers', 10, true);

下面是如何在不使用cume_dist()的情况下执行相同的操作(前面的行)/(总行数),并添加一些逻辑来排除不是当前的行:

SELECT
  target,
  question,
  value,
  current,
  (
    -- this is the count of partition rows preceding this row
    SELECT COUNT(1)
    FROM my_table AS inner_table
    WHERE
      inner_table.question = outer_table.question AND
      current = true AND
      inner_table.value <= outer_table.value
  )::real / (
    -- this is the total number of rows for this question
    SELECT COUNT(1)
    FROM my_table AS inner_table
    WHERE
      inner_table.question = outer_table.question AND
      current = true
  )::real * 100.0 AS percentile
FROM my_table AS outer_table;

Here是此查询的一个小链接

相关问题