首页 > 数据库 >SQL.LeetCode(1321)餐馆营业额变化增长

SQL.LeetCode(1321)餐馆营业额变化增长

时间:2024-09-12 11:51:35浏览次数:11  
标签:customer 01 amount 1321 2019 SQL visited LeetCode select

表: Customer

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| customer_id   | int     |
| name          | varchar |
| visited_on    | date    |
| amount        | int     |
+---------------+---------+
在 SQL 中,(customer_id, visited_on) 是该表的主键。
该表包含一家餐馆的顾客交易数据。
visited_on 表示 (customer_id) 的顾客在 visited_on 那天访问了餐馆。
amount 是一个顾客某一天的消费总额。

你是餐馆的老板,现在你想分析一下可能的营业额变化增长(每天至少有一位顾客)。

计算以 7 天(某日期 + 该日期前的 6 天)为一个时间段的顾客消费平均值。average_amount 要 保留两位小数。

结果按 visited_on 升序排序

返回结果格式的例子如下。

示例 1:

输入:
Customer 表:
+-------------+--------------+--------------+-------------+
| 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         | 
+-------------+--------------+--------------+-------------+
输出:
+--------------+--------------+----------------+
| 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         |
+--------------+--------------+----------------+
解释:
第一个七天消费平均值从 2019-01-01 到 2019-01-07 是restaurant-growth/restaurant-growth/ (100 + 110 + 120 + 130 + 110 + 140 + 150)/7 = 122.86
第二个七天消费平均值从 2019-01-02 到 2019-01-08 是 (110 + 120 + 130 + 110 + 140 + 150 + 80)/7 = 120
第三个七天消费平均值从 2019-01-03 到 2019-01-09 是 (120 + 130 + 110 + 140 + 150 + 80 + 110)/7 = 120
第四个七天消费平均值从 2019-01-04 到 2019-01-10 是 (130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86

这道题的难点在于我们如何基于当天拿到前6天的数据,以来求取这七天的平均数。

而且拿到了这样的数据我们还得想怎么去除不满足前面有6天的数据,例如示例的2019-01-01,它前面都没有六天的数据,所以就没有必要展示。

我们知道一定的是基于七天的一个度量去进行计算,所以我们可以联想到一个窗口,窗口的大小固定为7,基于当天我们这个窗口包含住前6天的数据进行计算来得到结果。

我们知道MySQL是有窗口函数的,但是其实窗口函数是有定长的窗口的功能。

语法为:

<window_function> OVER (
  [PARTITION BY partition_column]
  [ORDER BY order_column]
  [ROWS or RANGE BETWEEN <frame_start> AND <frame_end>]
)

后面的ROWS与RANGE就是用来制定窗口的大小的。

详情可以查看我上一篇定长窗口的SQL

https://blog.csdn.net/m0_65013257/article/details/142170042?spm=1001.2014.3001.5501

 现在我们已经有了计算固定窗口大小的函数,但我们还得需要一个细节。每一天是有多条记录的,也就是会有多个顾客购买,我们应该是基于当天的总额来进行窗口的计算。所以我们首先得算出每一天的总额

select visited_on,sum(amount) amount
from customer
group by visited_on

现在我们可以基于这样一个基础表进行计算。需要运用两次窗口函数。

一次窗口计算七天内的总和。一次窗口计算七天内的平均数。

写出对应的SQL

select visited_on,
sum(amount) over (order by visited_on rows 6 preceding) amount,
avg(t1.amount) over (order by visited_on rows 6 preceding) as average_amount
from (
    select visited_on,sum(amount) amount
    from customer
    group by visited_on
) t1

这里还有一点瑕疵,平均数题目的示例中需要保留两位小数。所以我们还要使用Round函数

select visited_on,
sum(amount) over (order by visited_on rows 6 preceding) amount,
round(avg(t1.amount) over (order by visited_on rows 6 preceding),2) as average_amount
from (
    select visited_on,sum(amount) amount
    from customer
    group by visited_on
) t1

现在我们就算出每一天的七天内的平均额度与总额度了。但是我们还得需要去除未能有前面6天数据的数据。那这样我们应该有两种想法。一种应该是跳过,还有一种应该是基于一种判定,我们只需要判定后的数据。

我这里先阐述跳过的方法。我们可以跳过前六天的数据,然后获取后面所有的数据即可,但是遇到一个麻烦的事,MySQL当中没有这样的语法说获取到后面所有的数据。但我们可以拟一个较大的数,这样就可以满足我们的需求。

完整的SQL如下

select visited_on,
sum(amount) over (order by visited_on rows 6 preceding) amount,
round(avg(t1.amount) over (order by visited_on rows 6 preceding),2) as average_amount
from (
    select visited_on,sum(amount) amount
    from customer
    group by visited_on
) t1
limit 100000000000000 offset 6

那我们如何基于第二种想法解题呢,或者说还有其他方法吗?

实际上我们可以减少一次窗口函数的使用,因为有了七天的总额度,我们可以直接除以7就可以得倒平均数。而除去前六天的数据可以已时间的差值来进行判定,拿到所有时间中的最小值,然后当天的时间剪去最小值的时间如果大于等于6就行。

我们基础表不变,还是需要每一天的总额。

select visited_on,sum(amount) amount
        from customer
        group by visited_on
        ) t1

然后运用一次窗口计算总额

select visited_on,
    sum(amount) over (order by visited_on rows 6 preceding) amount
    from (
        select visited_on,sum(amount) amount
        from customer
        group by visited_on
        ) t1

然后筛选时间的SQL语句为

where datediff(visited_on,(select min(visited_on) from customer)) >= 6

然后算出平均数即可。总SQL为

select visited_on,
amount,
round(amount / 7,2) as average_amount
from
(
    select visited_on,
    sum(amount) over (order by visited_on rows 6 preceding) amount
    from (
        select visited_on,sum(amount) amount
        from customer
        group by visited_on
        ) t1
) t2
where datediff(visited_on,(select min(visited_on) from customer)) >= 6

标签:customer,01,amount,1321,2019,SQL,visited,LeetCode,select
From: https://blog.csdn.net/m0_65013257/article/details/142170943

相关文章

  • 【PostgreSQL】安装及创建空间数据库
    简介PostgreSQL是一个功能强大的开源对象关系数据库系统下载地址PostgreSQL:Downloads由于我电脑上安装的是arcgispro3.1所以需要下载对应的postgresql版本PostgreSQL12对应的PostGIS版本主要是3.5.0或更高版本。安装一般设置为postgresql安装扩......
  • Mysql Non cluster combined fields select where order by field different time co
    usemydb;droptableifexistst1;createtablet1(idintauto_incrementprimarykey,firstnamevarchar(100)notnulldefault'',lastnamevarchar(100)notnulldefault'',indexfn_ln_index(firstname,lastname)); FLUSHBINARYLO......
  • [昌哥IT课堂]|如何确定 MySQL 服务器是否为 LTS 版本(译)
     根据支持LTS(长期支持)发布的新发布模型,给定的MySQL服务器将分为以下两类:要么是LTS版本。要么是创新版本。本博客文章将解释如何确定给定的MySQL服务器是否为LTS版本。 定义发布类型MySQL服务器源代码存储库中包含一个名为MYSQL_VERSION的文件,用于定义当前发......
  • 爬楼梯(LeetCode)&冒泡和选择排序
    目录一、爬楼梯(LeetCode)1、题目2、代码二、冒泡排序三、选择排序一、爬楼梯(LeetCode)1、题目2、代码二、冒泡排序三、选择排序......
  • mysql 5.7 删除ibdata1 、ib_logfile 文件的数据恢复
    简介:本文记录删除ibdata1、ib_logfile文件被意外删除且无法还原或损坏的解决方案,当删除后没有重启mysql可以查询进程号,找到删除的文件可以还原回来。参考其他文章。本文介绍ibdata1、ib_logfile文件无法找到或异常没有备份的情况处理。 新安装一台mysql用作从库......
  • pbootcms升级提示 执行SQL发生错误!错误:duplicate column name: picstitle
    当你在升级PBootCMS时遇到“执行SQL发生错误!错误:duplicatecolumnname:picstitle”的问题,这通常表示在升级过程中,数据库表结构的变更脚本未能正确执行,导致新的字段名称与现有字段冲突。以下是如何解决这个问题的一些步骤:解决方案备份数据库:在进行任何数据库操作之前,务必先......
  • MySQL生成指定月份所有日期列表
    SELECTADDDATE(month.firstDay,days.day-1)ASmonthDateFROM(SELECT1ASDAYUNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4UNIONALLSELECT5UNIONALLSELECT6UNIONALLSELECT7UNIONALLSELECT8UNIONALLSELECT9UNIONALLSELECT10UNI......
  • openGauss和PostgreSQL差异对比
    检查点在PostgreSQL中的检查点叫全量检查点,执行时会将buffer中的所有的脏页刷到磁盘,需要在一定时间内完成刷脏页的操作,导致数据库运行性能波动较大。同时全量检查点开始时需要遍寻内存中的所有脏页,内存越大,寻找脏页的时间也越长,具体过程如下:遍历所有BUFFER,将当前时刻的所有脏块状态......
  • Redis、Nginx、SQLite、Elasticsearch等开源软件成功的原因及它们对IT技术人员的启示
    引言这些年在自研产品,对于如何做好产品进行了一些思考。随着开源软件的蓬勃发展,许多开源项目已经成为IT行业的核心组成部分。像Redis、Nginx、SQLite、Elasticsearch这些知名的开源软件,已经成为了开发者的首选工具。这些开源软件不仅在技术性能上取得了重大突破,还在社区建设、生......
  • LeetCode Hot100刷题记录-142. 环形链表 II
    给定一个链表的头节点head,返回链表开始入环的第一个节点。如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如果pos是......