具有聚合函数的CASE会大大减慢查询速度,这是一种更好的方法吗?

时间:2012-05-28 10:45:01

标签: performance postgresql aggregate-functions case

SELECT CASE WHEN avg(count)>12 THEN 5
            WHEN avg(count)>8  THEN 4
            WHEN avg(count)>2  THEN 3
            WHEN avg(count)>1  THEN 2
            ELSE 1
            END,madeby
FROM (SELECT M.month,(SELECT count(*)
                     FROM Booking
                     WHERE date_trunc('month',starttime)=month
                         AND madeby=M.madeby
                     ) AS count,M.madeby
     FROM (SELECT date_trunc('month',generate_series(min(starttime),
                            current_timestamp,interval '1 month')::timestamp)
                            AS month,madeby
          FROM Booking
          GROUP BY madeby
     ) AS M
) AS BookingsPerMonth
GROUP BY madeby;

现在我需要在那里进行计算,我不是在质疑。我猜这个问题是它计算了四次聚合函数avg。时间的差异从CASE的约17秒到没有的4.5秒(尽管我当时缺乏足够的信息)

有没有办法可以通过变量存储或其他方式对其进行优化,以便将时间缩短到4.5秒?

2 个答案:

答案 0 :(得分:2)

SELECT  
    CASE 
        WHEN avg_count > 12 THEN 5
        WHEN avg_count > 8  THEN 4
        WHEN avg_count > 2  THEN 3
        WHEN avg_count > 1  THEN 2
        ELSE 1
    END,
    madeby
FROM (
    SELECT avg(count) as avg_count, madeby
    FROM (
        SELECT 
            M.month,
            (
                SELECT count(*)
                FROM Booking
                WHERE date_trunc('month',starttime)=month AND madeby=M.madeby
            ) AS count, 
            M.madeby
        FROM (
            SELECT 
                date_trunc('month',generate_series(min(starttime),
                current_timestamp,interval '1 month')::timestamp) AS month,
                madeby
            FROM Booking
            GROUP BY madeby
        ) AS M
    ) AS BookingsPerMonth
    GROUP BY madeby
) AS Averages;

答案 1 :(得分:0)

我会尝试让PG只对其进行一次计算,就像这样(从我的头脑中):

反而做

SELECT CASE WHEN avg(count)>12 THEN 5
            WHEN avg(count)>8  THEN 4
...

SELECT CASE WHEN avgcount>12 THEN 5
            WHEN avgcount>8  THEN 4
...

然后替换

FROM (SELECT M.month,(SELECT count(*)
...
                     ) AS count,M.madeby

FROM (SELECT avg(M.month),(SELECT count(*)
...
                     ) AS avgcount,M.madeby

你的,S。