与查询具有相同 WHERE 子句的子查询
Posted
技术标签:
【中文标题】与查询具有相同 WHERE 子句的子查询【英文标题】:Subquery with the same WHERE clause as query 【发布时间】:2015-02-27 19:35:13 【问题描述】:在 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
子句,因为timeA
和timeB
每次都不同)在一个视图中,然后我只是在这个视图中使用特定的timeA
和@ SELECT *
987654328@ 在WHERE
子句中。
现在考虑以下查询:
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 子句中实际的timeA
和timeB
。在查询视图本身之前,这些时间是未知的。
编辑: 另一个问题是someOtherColumn
也在第一个查询中被选中(可能还有一些我也想在视图中合并的其他列) - 因为聚合函数正在使用中。
任何想法如何实现这一目标?或者也许欢迎一些不同的方法!
【问题讨论】:
【参考方案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
:
根据数据分布和基数,其他查询技术可能会也可能不会更快:
Optimize GROUP BY query to retrieve latest record per user【讨论】:
谢谢 - 我正在使用 9.4。一定要试试这个! 好的,这很好用!但是我现在需要克服另一个问题 - 因为现在正在使用聚合函数,所以我不能选择比 ORDER BY 或 GROUP BY 子句中指定的列更多的列,对吗?我得到了臭名昭著的column "someOtherColumn" must appear in the GROUP BY clause or be used in an aggregate function
@Right,然后我们需要将其作为窗口函数运行。我又加了一些。您确实想要每个发件人的总和,对吗?
哇,我无语了!非常感谢!
经过进一步调查,我认为值得注意的是,由于使用了 window 函数,Postgres 在查询时不会“下推”WHERE
-clause风景。这很可能会对性能产生一些影响。参考:***.com/questions/7533877/…以上是关于与查询具有相同 WHERE 子句的子查询的主要内容,如果未能解决你的问题,请参考以下文章