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

Subquery with the same WHERE clause as query

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

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 * 从此视图在 WHERE 子句中使用特定的 timeAtimeB

现在考虑以下查询:

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 查询的总分。

我想将此查询(可能作为子查询)合并到我的视图中,这样我还可以看到每个不同发件人的 "score"。明显的问题是 "score query" 依赖于 WHERE 子句中的实际 timeAtimeB。在查询视图本身之前,这些时间是未知的。

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

有什么实现方法吗?或者也许欢迎一些不同的方法!

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正确:

  • Select first row in each GROUP BY group?

DISTINCT ON 应用 after 聚合函数,这就是为什么您可以将两者组合在一个 SELECT 中。考虑 SELECT 查询中的事件序列:

  • Best way to get result count before LIMIT was applied

关于新聚合 FILTER 子句(需要 Postgres 9.4):

  • How can I simplify this game statistics query?

如果您想添加更多(未聚合的)列,您需要 运行 此为 window function

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

  • PostgreSQL sort by datetime asc, null first?

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

  • Optimize GROUP BY query to retrieve latest record per user