PostgreSQL 中的 PERCENTILE_DISC() 作为窗口函数

Posted

技术标签:

【中文标题】PostgreSQL 中的 PERCENTILE_DISC() 作为窗口函数【英文标题】:PERCENTILE_DISC() in PostgreSQL as a window function 【发布时间】:2016-09-20 13:09:52 【问题描述】:

我们正在将我们的系统从 SQL Server 移植到 PostgreSQL。因此,我们计算了过去 3 个月所有日期所有公司的平均每日营业额。以下是相同的简化查询

SELECT B.Company, B.Dt, B.Turnover,   (Select distinct
PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY Turnover)  OVER (PARTITION
BY B.Company, B.Dt) from Example_Tbl AS G  where G.Company = B.Company
and G.Dt <= B.Dt and  G.Dt > DateAdd(dd, -92, B.Dt)) as
Med_3m_Turnover FROM Example_Tbl B;

问题在于 PostgreSQL 不支持将percentile_disc() 用作窗口函数。错误信息是:

错误:有序集聚合 percentile_disc 不支持 OVER

有什么方法可以在 PostgreSQL 中使用其他东西来实现相同的功能。

编辑:这是 Example_Tbl 中的示例输入数据

Company  Dt   Turnover 
x        1    10 
x        2    45 
x        3    20 
y        1    300 
y        2    100  
y        3    200

输出应如下所示。请注意,我们现在忽略 3 个月,每个公司只有 3 行

Company  Dt   Turnover   Med_3m_Turnover
x        1    10         10 
x        2    45         10 or 45 depending on percentile_desc
x        3    20         20 
y        1    300        300 
y        2    100        300 or 100 depending on percentile_desc
y        3    50         100  

【问题讨论】:

我一定没有完全理解您的查询,因为我不确定select distinct percentile_disc(... 部分有时不会返回超过一行,这会产生错误。 @sstan。如果没有 distinct 子句,子查询将返回多个值并引发错误。不同的是完全停止。 在我看来您根本不需要OVER,因为您的子查询应该只返回一行,然后只使用WITHIN GROUP 而没有WINDOW FUNCTION。 @John:我明白了,但是查询不能返回多个 distinct 值吗?这是我不清楚的部分。我之所以这么说是因为partition子句是byB.Company, B.Dt,而子查询在G.Dt &lt;= B.Dt上有一个过滤条件,这意味着可能有多个B.Company, B.Dt组合,因此也可以返回多个不同的percentile_disc价值观。如果您的查询有效,我知道我一定是错的,但这就是我试图理解的地方。 @John:实际上,我刚刚意识到为什么查询永远不会失败。这是因为partition by 子句使用B.Company, B.Dt(该行的常量值)而不是G.Company, G.Dt。不确定这是否是故意的(我不这么认为),但这就是防止错误的原因。不确定你是否得到了你想要的结果。 【参考方案1】:

您的 partition by 子句 (PARTITION BY B.Company, B.Dt) 正在使用来自外部查询的值(别名 B),而不是子查询(别名 G),这对我来说一开始并不明显。因为 B.companyB.Dt 的值对于子查询的每次执行都是恒定的,所以你的分区子句实际上与简单地写成这样没有什么不同:

... over (partition by 1)

如果你愿意,你可以在 SQL Server 中测试它,但你会发现结果是一样的。现在,我不知道使用B.Company, B.Dt 是不是故意的,但实际上,这意味着partition by 子句实际上并没有对任何东西进行分区。

因此,对您来说,好消息是要在 PostgreSQL 中编写等效查询,您只需完全省略 OVER (PARTITION BY B.Company, B.Dt) 子句,其行为将与 SQL Server 中相同。

【讨论】:

谢谢@sstan。是的,Query 与“over (partition by 1)”相同。我想我们一定把它放在那里,因为 SQL Server 需要 WITHIN GROUP 和 OVER 子句,尽管我不知道为什么。没有它们中的任何一个,它都会出错。我将删除 postgres 中的分区引用。当我继续迁移时,我确信我会遇到需要两者的查询。当我到达那里时会发布另一个问题。再次感谢

以上是关于PostgreSQL 中的 PERCENTILE_DISC() 作为窗口函数的主要内容,如果未能解决你的问题,请参考以下文章

红移中的 PERCENTILE_CONT()

9_InfluxDB常用函数选择类函数(TOP() BOTTOM() FIRST() LAST() MAX() MIN() PERCENTILE())

Hive:percentile_approx 原理与实现

apache spark sql中的等效percentile_cont函数

如何在 postgreSQL 中创建 generate_series 函数?

急求Excel 函数percentile 是怎样算出来的?如:percentile(A1:A8, 0.8) , 是A1至A8相加,再乘以0.8吗?