在通过聚合聚合过滤时避免重复计算?

时间:2013-01-03 02:42:05

标签: sql aggregate-functions teradata

我试图推动过去一年每月销售量超过10,000个单位至少6个月的商店的月度销售额。我的源销售表是每日。因此,我计算所有商店所有月份的销售额,然后计算出哪些商店超过10,000个单位6次,并使用该商店列表作为查询的过滤器,我在该查询中计算过滤商店的所有月份。

因此,我基本上在同一个查询中执行两次相同的聚合计算sum(units_sold)

select
    store_location,
    sales_date - extract(day from sales_date) + 1 as sales_month,
    sum(units_sold) as monthly_sales,   /* I already calculated this!  How to re-use? */
    case when sum(units_sold) > 10000 then 1 else 0 end as exceeded_10000 

from
    daily_sales

where
    sales_date between '2012-01-01' and '2012-12-31' and
    store_location in (
        select
            store_location
        from (
                select
                    store_location,
                    sales_date - extract(day from sales_date) + 1 as sales_month,
                    case when sum(units_sold) > 10000 then 1 else 0 end as exceeded_10000   /* evaluated per month, per store */
                from
                    daily_sales
                where
                    sales_date between '2012-01-01' and '2012-12-31'
                group by
                    store_location,
                    sales_date - extract(day from sales_date) + 1
        ) a
        group by
            store_location
        having
            sum(exceeded_10000) > 6   /* which stores had 6 months over 10000 ? */ 
    )

group by
    store_location,
    sales_date - extract(day from sales_date) + 1

这似乎效率低下 - 我已经在内部(过滤)查询中按月计算sum(units_sold),但我无法找到重用这些月总数的方法。您会注意到,查询b不会按月分组,因为它会累计销售额超过10,000的月数 - 这是我在标题中引用的聚合的总和。

Teradata不支持PIVOT功能,我宁愿不使用大量的CASE WHEN来模拟一个支点,然后每个月检查一行。

有没有办法让这个查询更有效率?要重新使用我在内部查询中计算的月销售总额吗?它可以在不同的RDBMS平台而不是Teradata上进行简化吗?谢谢。

1 个答案:

答案 0 :(得分:3)

您的查询似乎没有做您想要的。外部查询按月分组,这不是必需的。

以下查询返回超过6个月且销售额超过10,000的位置:

select store_location, sum(month_units_sold) as totalunits,
        sum(exceeded_10000) as months_over_10000
from (select store_location,
             sales_date - extract(day from sales_date) + 1 as sales_month,
             sum(units_sold) as month_units_sold
             (case when sum(units_sold) > 10000 then 1 else 0 end) as exceeded_10000   /* evaluated per month, per store */
      from daily_sales
      where sales_date between '2012-01-01' and '2012-12-31'
      group by store_location, sales_date - extract(day from sales_date) + 1
    ) t
group by store_location
having sum(exceeded_10000) >= 6

如果您想要按月购买每个商店的信息,请使用窗口函数计算超出的月数:

select *
from (select t.*,
             SUM(exceeded_10000) over (partition by store_location) s MonthsExceeded10000
      from (select store_location,
                   sales_date - extract(day from sales_date) + 1 as sales_month,
                   sum(units_sold) as month_units_sold
                   (case when sum(units_sold) > 10000 then 1 else 0 end) as exceeded_10000   /* evaluated per month, per store */
            from daily_sales
            where sales_date between '2012-01-01' and '2012-12-31'
            group by store_location, sales_date - extract(day from sales_date) + 1
          ) t
    ) t
where MonthsExceeded10000