我试图推动过去一年每月销售量超过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上进行简化吗?谢谢。
答案 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