SQL:如何选择窗口函数和聚合函数

时间:2015-02-25 21:01:51

标签: sql select aggregate-functions aster

我想知道如何混合选择列,汇总值以及从分区中选择'。如果这是一个重复的问题,请告诉我!

我的意思的一个例子:

给出示例事务日志:

ID     Food    Date     Cost
1      Apple   5/1/14   10
1      Apple   5/4/14   8
1      Apple   5/6/14   15
1      Pear    5/2/14   25
2      Apple   5/3/14   15

目标是选择每个唯一ID /食品组合,首次购买(按日期),上次购买的成本以及平均成本。

输出如下:

ID   Food    First_Cost    Last_Cost     Avg_Cost
1    Apple   10            15            11
1    Pear    25            25            25
2    Apple   15            15            15

我已经查看了OVER - PARTITION(Select first row in each GROUP BY group?)以及与聚合函数(https://dba.stackexchange.com/questions/41494/select-first-row-grouping-add-aggregate-function)一起分组,但似乎都没有回答这个具体问题。

这是我尝试完成的代码示例:

select id
      ,food
      ,firstrow(cost) OVER(PARTITION BY id, food ORDER BY date asc as first_cost
      ,avg(cost) from table
group by id, food;

使用ROWNUMBER() OVER(PARTITION...)然后使用where子句进行过滤似乎不起作用,因为聚合函数将关闭。

一个解决方案总是可以创建一个包含第一个的表,一个包含最后一个,一个包含平均值,并将三者连接在一起,但我正在寻找更清洁的东西。

修改: 根据jpw的评论,Aster确实有first_value()窗口函数。但是,它的问题是我订购或分区的列必须包含在groupby子句中。他的建议和一个解决方案可能是将所有聚合函数更改为窗口函数并完全消除groupby。

仍然希望看到一个更清洁的解决方案或确认这是不可能的!

2 个答案:

答案 0 :(得分:0)

查询:

select id
      ,food
      ,first_value(cost) OVER(PARTITION BY id, food ORDER BY exp_date asc) as first_cost
      ,first_value(cost) OVER(PARTITION BY id, food ORDER BY exp_date desc) as last_cost
      ,avg(cost) OVER(PARTITION BY id, food ORDER BY exp_date asc) as avg_cost
from sm_fruits

让你关闭:

    id  Food    first_cost  last_cost   avg_cost
1   1   Apple   10          15          11.00
2   1   Apple   10          15          11.00
3   1   Apple   10          15          11.00
4   1   Pear    25          25          25.00
5   2   Apple   15          15          15.00

答案 1 :(得分:-2)

您可以将表格交叉应用于自己(两次)以获取该日期的最大/最小日期和项目成本。

阅读十字架应用其晚餐有用

 select id
      ,food
      ,LastCost
      ,FirstCost
      ,avg(cost) from TABLE t1
       Cross APPLY(
                    SELECT MAX(date), cost AS LastCost FROM TABLE t2 WHERE t2.food = t1.food
                  ) maxdate
       Cross APPLY(
                    SELECT MIN(date), cost AS FirstCost FROM TABLE t3 WHERE t3.food = t1.food
                  ) mindate
group by id, food;