sql(聚合的使用)

##SQL的聚合为题
全局聚合: Group by
局部聚合:窗口函数

  • 1.聚合某一个区间
  • 2.新维度(这个维度不存在,你需要自己创造)
  • 3.还可以求最后一个值(通过聚合结果值而不是排名序号)

######聚合某一个区间

1321. Restaurant Growth

Table: Customer

±--------------±--------+
| Column Name | Type |
±--------------±--------+
| customer_id | int |
| name | varchar |
| visited_on | date |
| amount | int |
±--------------±--------+
(customer_id, visited_on) is the primary key for this table.
This table contains data about customer transactions in a restaurant.
visited_on is the date on which the customer with ID (customer_id) have visited the restaurant.
amount is the total paid by a customer.

You are the restaurant owner and you want to analyze a possible expansion (there will be at least one customer every day).

Write an SQL query to compute moving average of how much customer paid in a 7 days window (current day + 6 days before) .

The query result format is in the following example:

Return result table ordered by visited_on.

average_amount should be rounded to 2 decimal places, all dates are in the format (‘YYYY-MM-DD’).

Customer table:
±------------±-------------±-------------±------------+
| customer_id | name | visited_on | amount |
±------------±-------------±-------------±------------+
| 1 | Jhon | 2019-01-01 | 100 |
| 2 | Daniel | 2019-01-02 | 110 |
| 3 | Jade | 2019-01-03 | 120 |
| 4 | Khaled | 2019-01-04 | 130 |
| 5 | Winston | 2019-01-05 | 110 |
| 6 | Elvis | 2019-01-06 | 140 |
| 7 | Anna | 2019-01-07 | 150 |
| 8 | Maria | 2019-01-08 | 80 |
| 9 | Jaze | 2019-01-09 | 110 |
| 1 | Jhon | 2019-01-10 | 130 |
| 3 | Jade | 2019-01-10 | 150 |
±------------±-------------±-------------±------------+

Result table:
±-------------±-------------±---------------+
| visited_on | amount | average_amount |
±-------------±-------------±---------------+
| 2019-01-07 | 860 | 122.86 |
| 2019-01-08 | 840 | 120 |
| 2019-01-09 | 840 | 120 |
| 2019-01-10 | 1000 | 142.86 |
±-------------±-------------±---------------+

1st moving average from 2019-01-01 to 2019-01-07 has an average_amount of (100 + 110 + 120 + 130 + 110 + 140 + 150)/7 = 122.86
2nd moving average from 2019-01-02 to 2019-01-08 has an average_amount of (110 + 120 + 130 + 110 + 140 + 150 + 80)/7 = 120
3rd moving average from 2019-01-03 to 2019-01-09 has an average_amount of (120 + 130 + 110 + 140 + 150 + 80 + 110)/7 = 120
4th moving average from 2019-01-04 to 2019-01-10 has an average_amount of (130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/restaurant-growth
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

窗口函数先聚合,并且在函数中选择区间

/* Write your PL/SQL query statement below */
SELECT T.*, ROUND(T.AMOUNT / 7, 2) AVERAGE_AMOUNT
  FROM (SELECT TO_CHAR(VISITED_ON, 'yyyy-mm-dd') VISITED_ON,
        SUM(AMOUNT) OVER(ORDER BY VISITED_ON, VISITED_ON ROWS BETWEEN 6 PRECEDING AND    
        CURRENT ROW)    
        AMOUNT
          FROM (SELECT VISITED_ON, SUM(AMOUNT) AMOUNT
                  FROM CUSTOMER
                 GROUP BY VISITED_ON)) T
 WHERE T.VISITED_ON >= (SELECT MIN(VISITED_ON) + 6 FROM CUSTOMER)

######3.最后一个值

1204. 最后一个能进入电梯的人

有时候你的需求就是会有一个在原表中不存在的维度,这时候你需要自己创造一个维度

表: Queue

±------------±--------+
| Column Name | Type |
±------------±--------+
| person_id | int |
| person_name | varchar |
| weight | int |
| turn | int |
±------------±--------+
person_id 是这个表的主键。
该表展示了所有等待电梯的人的信息。
表中 person_id 和 turn 列将包含从 1 到 n 的所有数字,其中 n 是表中的行数。

电梯最大载重量为 1000。

写一条 SQL 查询语句查找最后一个能进入电梯且不超过重量限制的 person_name 。题目确保队列中第一位的人可以进入电梯 。

查询结果如下所示 :

Queue 表
±----------±------------------±-------±-----+
| person_id | person_name | weight | turn |
±----------±------------------±-------±-----+
| 5 | George Washington | 250 | 1 |
| 3 | John Adams | 350 | 2 |
| 6 | Thomas Jefferson | 400 | 3 |
| 2 | Will Johnliams | 200 | 4 |
| 4 | Thomas Jefferson | 175 | 5 |
| 1 | James Elephant | 500 | 6 |
±----------±------------------±-------±-----+

Result 表
±------------------+
| person_name |
±------------------+
| Thomas Jefferson |
±------------------+

为了简化,Queue 表按 trun 列由小到大排序。
上例中 George Washington(id 5), John Adams(id 3) 和 Thomas Jefferson(id 6) 将可以进入电梯,因为他们的体重和为 250 + 350 + 400 = 1000。
Thomas Jefferson(id 6) 是最后一个体重合适并进入电梯的人。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/last-person-to-fit-in-the-elevator
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/* Write your PL/SQL query statement below */
SELECT person_name
FROM Queue a
WHERE a.turn = (
	SELECT MAX(turn)
	FROM (
		SELECT a.turn, a.person_name, SUM(weight) OVER (ORDER BY turn) AS eleWeight
		FROM Queue a
	) a
	WHERE a.eleWeight <= 1000
)

作者:wo-de-tian-bug
链接:https://leetcode-cn.com/problems/last-person-to-fit-in-the-elevator/solution/you-ren-qiang-wo-ji-fen-by-wo-de-tian-bug/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

######2.新维度

1127. 用户购买平台

支出表: Spending

±------------±--------+
| Column Name | Type |
±------------±--------+
| user_id | int |
| spend_date | date |
| platform | enum |
| amount | int |
±------------±--------+
这张表记录了用户在一个在线购物网站的支出历史,该在线购物平台同时拥有桌面端(‘desktop’)和手机端(‘mobile’)的应用程序。
这张表的主键是 (user_id, spend_date, platform)。
平台列 platform 是一种 ENUM ,类型为(‘desktop’, ‘mobile’)。

写一段 SQL 来查找每天 仅 使用手机端用户、仅 使用桌面端用户和 同时 使用桌面端和手机端的用户人数和总支出金额。

查询结果格式如下例所示:

Spending table:
±--------±-----------±---------±-------+
| user_id | spend_date | platform | amount |
±--------±-----------±---------±-------+
| 1 | 2019-07-01 | mobile | 100 |
| 1 | 2019-07-01 | desktop | 100 |
| 2 | 2019-07-01 | mobile | 100 |
| 2 | 2019-07-02 | mobile | 100 |
| 3 | 2019-07-01 | desktop | 100 |
| 3 | 2019-07-02 | desktop | 100 |
±--------±-----------±---------±-------+

Result table:
±-----------±---------±-------------±------------+
| spend_date | platform | total_amount | total_users |
±-----------±---------±-------------±------------+
| 2019-07-01 | desktop | 100 | 1 |
| 2019-07-01 | mobile | 100 | 1 |
| 2019-07-01 | both | 200 | 1 |
| 2019-07-02 | desktop | 100 | 1 |
| 2019-07-02 | mobile | 100 | 1 |
| 2019-07-02 | both | 0 | 0 |
±-----------±---------±-------------±------------+
在 2019-07-01, 用户1 同时 使用桌面端和手机端购买, 用户2 仅 使用了手机端购买,而用户3 仅 使用了桌面端购买。
在 2019-07-02, 用户2 仅 使用了手机端购买, 用户3 仅 使用了桌面端购买,且没有用户 同时 使用桌面端和手机端购买。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/user-purchase-platform
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码中你必须创造一个both的维度

select temp1.spend_date, temp1.platform, 
       ifnull(temp3.total_amount, 0) total_amount, 
       ifnull(temp3.total_users,0) total_users
from
     (select distinct(spend_date), p.platform   
     from Spending,
         (select 'desktop' as platform union
          select 'mobile' as platform union
          select 'both' as platform
         ) as p 
      ) as temp1
left join 
   (select spend_date,platform, sum(amount) as total_amount, count(user_id) total_users
   from
         (select spend_date, user_id, 
             (case count(distinct platform)
             when 1 then platform
             when 2 then 'both'
             end
             ) as  platform, sum(amount) as amount
         from Spending
         group by spend_date, user_id
         ) as temp2
    group by spend_date, platform
   ) as  temp3
on temp1.platform = temp3.platform and temp1.spend_date = temp3.spend_date
### 使用SQL聚合函数的方法 #### 基本概念 SQL中的聚合函数用于对表中的数据进行汇总计算,常用来生成统计信息,例如总和、平均值、最大值、最小值等。这些函数可以单独使用,也可以与`GROUP BY`子句一起使用来对特定分组的数据执行操作[^1]。 #### 单独使用的例子 当不需要按任何条件分组时,可以直接应用聚合函数获取整个表格的相关统计数据: ```sql SELECT COUNT(*) FROM employees; ``` 这条语句返回employees表中记录的数量。 #### 结合 GROUP BY 子句的例子 为了更细致地分析数据,可以通过`GROUP BY`按照某些列的值将结果集划分为多个小组,并针对每一组独立地应用聚合函数: ```sql SELECT department, AVG(salary), SUM(bonus) FROM employees GROUP BY department; ``` 上述查询会给出各部门员工工资的平均数以及奖金总额。 #### 特殊情况处理 值得注意的是,并不是所有的聚合函数都能适用于所有类型的字段。比如,在一些数据库实现里像`MAX()`这样的函数就不能作用于流式数据上的字段上尝试这样做可能会引发错误,如SQLCODE -37错误[^2]。 对于自定义需求较高的场景下,则可能涉及到创建用户自定义聚合函数(UDAF),特别是在分布式计算框架如Apache Flink中。此时需遵循一定的开发模式,包括但不限于声明该函数为aggregate function并指定其输入输出类型,同时提供必要的逻辑实现方法如`create_accumulator()`, `accumulate()`, 和`get_value()`等[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值