将SQL查询与共享逻辑

时间:2017-08-08 12:34:41

标签: sql postgresql

我目前正在复制一个相当大的SQL聚合查询,以便我可以运行一次以返回整个数据集的指标,然后再次对每天的指标进行分组。

以下是计算总体指标的查询的简化示例。

SELECT
  sum(sentiment) FILTER (WHERE user = :user) AS total_sentiment,
  avg(sentiment) FILTER (WHERE user = :user) AS average_sentiment,
  count(messages) FILTER (WHERE sender = :user) AS total_messages
FROM
  "Messages"
WHERE
  date >= :start AND date < :end;

这是计算相同指标的计算器,但每天计算一次。

SELECT
  date_trunc('day', date) AS date,
  sum(sentiment) FILTER (WHERE user = :user) AS total_sentiment,
  avg(sentiment) FILTER (WHERE user = :user) AS average_sentiment,
  count(messages) FILTER (WHERE sender = :user) AS total_messages
FROM
  "Messages"
WHERE
  date >= :start AND date < :end;
GROUP BY 1
ORDER BY 1

有没有办法结合这两个查询而不必复制大部分逻辑?

以编程方式构建查询字符串是一种选择,但我绝对不会走这条路。

如果查询实际上和上面的例子一样简单,那么复制它们就不会有什么问题,但它们处理更复杂的连接和统计函数 - 保持它们同步已经很棘手。

理想情况下,输出将是一个表,其第一行包含总体指标,其余行将是每日计算。

2 个答案:

答案 0 :(得分:2)

最简单的方法是使用grouping sets

SELECT date_trunc('day', date) AS date,
       sum(sentiment) FILTER (WHERE user = :user) AS total_sentiment,
       avg(sentiment) FILTER (WHERE user = :user) AS average_sentiment,
       count(messages) FILTER (WHERE sender = :user) AS total_messages
FROM "Messages"
WHERE date >= :start AND date < :end
GROUP BY GROUPING SETS ( (), (date) );

答案 1 :(得分:1)

您可以使用窗口函数:

SELECT DISTINCT
  date_trunc('day', date) AS date,
  sum(sentiment) FILTER (WHERE user = :user) OVER() AS total_sentiment,
  avg(sentiment) FILTER (WHERE user = :user) OVER() AS average_sentiment,
  count(messages) FILTER (WHERE sender = :user) OVER() AS total_messages,
  sum(sentiment) FILTER (WHERE user = :user) OVER(PARTITION BY date_trunc('day', date)) 
     AS total_sentiment_per_day,
  ...
FROM "Messages"
WHERE  date >= :start AND date < :end;
ORDER BY 1