具有与查询相同的WHERE子句的子查询

时间:2015-02-27 19:35:13

标签: sql postgresql aggregate-functions window-functions aggregate-filter

在Postgres 9.4中,我有一个表格,其中包含不同发件人发送的用户电子邮件。我需要生成最近的不同发件人的列表,我正在使用以下查询:

SELECT DISTINCT ON (tableA.senderName) 
       tableA.senderName,tableA.received,tableA.someOtherColumn
FROM tableA 
WHERE tableA.received BETWEEN timeA AND timeB
ORDER BY tableA.senderName,tableA.received DESC

由于tableA包含所有发件人的所有邮件,因此此查询仅向我提供了不同发件人的最新邮件,并且运行良好。

实际上,我在视图中有完整的查询(WHERE子句除外,因为timeAtimeB每次都不同),然后我只是SELECT *从这个视图使用timeA子句中的特定timeBWHERE

现在考虑以下查询:

SELECT SUM(ts_rank_cd(tableA.precompTSVector,constantTSQuery)) AS score 
FROM tableA 
WHERE tableA.precomTSVector @@ constantTSQuery
AND tableA.sender = someParticularSender
AND tableA.received BETWEEN timeA AND timeB

给出了在给定时间范围内针对特定发件人的所有邮件搜索某些常量TS查询的总分。

我想将此查询(可能作为子查询)合并到我的视图中,这样我也可以看到每个不同发件人的“得分”。显而易见的问题是“得分查询”取决于WHERE子句中的实际timeAtimeB。在查询视图本身之前,这些时间是未知的。

编辑:另一个问题是在第一个查询中也选择了someOtherColumn(可能还有其他一些我想在视图中加入的列) - 因为正在使用聚合函数。

任何想法如何实现这一目标?或者也许欢迎一些不同的方法!

1 个答案:

答案 0 :(得分:1)

SELECT DISTINCT ON (senderName) 
       senderName, received -- add more columns as you please
     , SUM(ts_rank_cd(precompTSVector,constantTSQuery)) 
         FILTER (WHERE precomTSVector @@ constantTSQuery)
         OVER (PARTITION BY senderName) AS score 
FROM   tableA
WHERE  received BETWEEN timeA AND timeB
ORDER  BY senderName, received DESC;

首先,你需要DISTINCT ON正确:

在聚合函数之后

DISTINCT ON应用了,这就是为什么你可以将它们组合在一个SELECT中。考虑SELECT查询中的事件序列:

关于新的汇总FILTER条款(要求Postgres 9.4 ):

如果要添加更多(未聚合的)列,则需要将其作为window function运行。

如果received可以为NULL,则您需要使用DESC NULLS LAST

根据数据分布和基数,其他查询技术可能会更快或更快: