2017-08-08 22 views
1

我目前正在複製一個相當大的SQL聚合查詢,以便我可以運行一次以返回整個數據集的度量標準,然後再對每天的度量標準進行分組。將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

最簡單的方法是使用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

你可以使用窗口功能:

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