【SQL边干边学系列】08高级问题-4

文章目录

  • 前言
  • 回顾
  • 高级问题
    • 48.客户分组
    • 49.客户分组-修复null
    • 50.使用百分比的客户分组
    • 51.灵活的客户分组
  • 答案
    • 48.客户分组
    • 49.客户分组-修复null
    • 50.使用百分比的客户分组
    • 51.灵活的客户分组
  • 未完待续


前言

在这里插入图片描述
该系列教程,将会从实际问题出发,边干边学,逐步深入讲解SQL的各方面知识。

你需要完成所有的问题吗?绝对不是。介绍性的问题相当简单,所以你可以直接跳过到“中级问题”部分。如果你不是初学者,但不确定应该从哪里开始,请在“入门问题”部分看看问题和预期结果,并确保你理解这些概念。如果已经理解了这些概念,请开始阅读“中级问题”部分。

你想从这本书中复制代码并在你的服务器上运行?我建议你手动输入,而不是复制粘贴。为什么要去麻烦地重新打字呢?科学表明,打字的行为会在你的脑中留下更深刻的印象。当你只是复制和粘贴时,代码只是直接从你电脑里的一个窗口转到另一个窗口,而不会给你留下多少印象。但是当你把它打出来时,你必须集中精力,这非常有助于保留信息。

一旦你完成了所有的问题,将拥有一些在数据分析和高级Select语句使用方面非常有用的技能。当然,这并不是SQL的全部内容。还有修改数据(更新、插入、删除)、DDL(数据定义语言,即如何创建和修改数据库对象)、编程(如存储过程)和许多其他主题。

该系列教程中,只涉及到了使用Select语句检索数据的问题,这几乎是所有其他数据库主题的基础开端。


回顾

上篇文章👉《【SQL边干边学系列】07高级问题-3》 讲了部分高级问题,这篇接着讨论更多的高级问题。


高级问题

48.客户分组

假如想为现有客户做一个销售活动。希望想根据客户在2016年的订购量,将他们分组。然后,根据客户所在的群组,采用不同的销售材料。

客户分组类别为0到1000、1000到5000、5000到10000个,以及超过10000个。

这个查询的一个很好的起点是来自“高价值客户-总订单”这个问题的答案。我们不想展示2016年没有任何订单的客户。

按CustomerID对结果排序。

-- 预期结果
CustomerID CompanyName                        TotalOrderAmount CustomerGroup
---------- ---------------------------------- ---------------- -------------
ALFKI      Alfreds Futterkiste                2302.20          Medium
ANATR      Ana Trujillo Emparedados y helados 514.40           Low
ANTON      Antonio Moreno Taquería            660.00           Low
...
WHITC White Clover Markets 15278.90 Very High
WILMK Wilman Kala 1987.00 Medium
WOLZA Wolski Zajazd 1865.10 Medium
(81 row(s) affected)

提示如下

这是来自“高价值客户-总订单”问题的SQL,但没有针对订单总数超过10,000个的过滤器。

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
Where
  OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName
Order By TotalOrderAmount Desc;

你可以在CTE(common table expression)中使用上面的SQL,然后在“TotalOrderAmount”上使用Case语句。

49.客户分组-修复null

上一个问题的答案有一个错误。CustomerGroup中有一行的值为null。

修复SQL,使CustomerGroup字段中没有null。

-- 预期结果
CustomerID CompanyName                     TotalOrderAmount      CustomerGroup
---------- ------------------------------- --------------------- -------------
LILAS      LILA-Supermercado               5994.06               High
LINOD      LINO-Delicateses                10085.60              Very High
LONEP      Lonesome Pine Restaurant        1709.40               Medium
...

提示如下

CustomerID为MAISD的总订单量是多少?这与我们的CustomerGroup边界有何关系?

使用“between”很适合整数值。然而,我们正在分析的字段是Money,它有小数位。因此不能使用下面的SQL:

when TotalOrderAmount between 0 and 1000 then 'Low'

而应该使用下面的SQL:

when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'

50.使用百分比的客户分组

根据上面的查询,显示所有已定义的客户组,以及每个组中的百分比。按每一组的总数排序,按降序排序。

-- 预期结果
CustomerGroup TotalInGroup PercentageInGroup
------------- ------------ ---------------------------------------
Medium        35           0.432098765432
Low           20           0.246913580246
High          13           0.160493827160
Very High     13           0.160493827160
(4 row(s) affected)

提示如下

作为起点,你可以使用问题“客户分组-修复null”中的答案。

我们不再需要在最终的输出中显示CustomerID和CompanyName。但是,我们需要计算每个CustomerGrouping组中有多少客户。你可以创建另一个CTE级别,以便获得最终输出的每个CustomerGrouping中的计数。

51.灵活的客户分组

我们希望根据客户订购的金额来完全灵活地分组。我们不想为了更改客户组的边界而不得不编辑SQL。

你需要一个叫做客户组阈值的表(CustomerGroupThreshold),仅使用从2016年开始的订单。

-- 预期结果
CustomerID CompanyName                        TotalOrderAmount CustomerGroupName
---------- ---------------------------------- ---------------- --------------------
ALFKI     Alfreds Futterkiste                 2302.20          Medium
ANATR     Ana Trujillo Emparedados y helados  514.40           Low
ANTON     Antonio Moreno Taquería             660.00           Low
...
WHITC     White Clover Markets                15278.90         Very High
WILMK     Wilman Kala                         1987.00          Medium
WOLZA     Wolski Zajazd                       1865.10          Medium
(81 row(s) affected)

作为起点,使用问题“使用百分比的客户分组”中的第一个CTE语句

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
From Customers
 join Orders
 on Orders.CustomerID = Customers.CustomerID
 join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName

提示:当考虑如何使用CustomerGroupThreshold表时,请注意,当连接到一个表时,你不仅可以使用一个等值连接(=),还可以使用其他操作符,如between、>或< 。


答案

48.客户分组

答案

;with Orders2016 as (
 Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
 Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
 Group by
 Customers.CustomerID
 ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroup =
 Case
 when TotalOrderAmount between 0 and 1000 then 'Low'
 when TotalOrderAmount between 1001 and 5000 then 'Medium'
 when TotalOrderAmount between 5001 and 10000 then 'High'
 when TotalOrderAmount > 10000 then 'Very High'
 End
from Orders2016
Order by CustomerID

讨论

CTE很适合解决这个问题,但这并不是严格必要的。你也可以使用这样的SQL:

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 ,CustomerGroup =
 Case
 when SUM(Quantity * UnitPrice) between 0 and 1000 then 'Low'
 when SUM(Quantity * UnitPrice) between 1001 and 5000 then 'Medium'
 when SUM(Quantity * UnitPrice) between 5001 and 10000 then 'High'
 when SUM(Quantity * UnitPrice) > 10000 then 'Very High'
 End
From Customers
 Join Orders
   on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
   on Orders.OrderID = OrderDetails.OrderID
Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName

这给出了相同的结果,但请注意,TotalOrderAmount被重复了5次,包括Case语句中的4次。

最好避免重复这样的计算。这些计算结果通常会非常复杂和难以阅读,而且你只想把它们放在一个地方。在一些简单的情况下,比如 Quantity * UnitPrice,这并不一定是一个问题。但大多数时候,你应该避免重复任何计算和代码。记住——“不要重复你自己”。

49.客户分组-修复null

答案

;with Orders2016 as (
 Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
 Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
 Group by
 Customers.CustomerID
 ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroup =
 case
   when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
   when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
   when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
   when TotalOrderAmount >= 10000 then 'Very High'
 end
from Orders2016
Order by CustomerID

讨论

正如你在上述问题中所看到的那样,了解你正在处理的数据类型以及理解它们之间的差异对于获得正确的结果非常重要。使用“between”对于整数值就可以,但对于Money则不行。

50.使用百分比的客户分组

答案

;with Orders2016 as (
 Select
   Customers.CustomerID
   ,Customers.CompanyName
   ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
   join Orders
     on Orders.CustomerID = Customers.CustomerID
   join OrderDetails
   on Orders.OrderID = OrderDetails.OrderID
 Where
   OrderDate >= '20160101'
   and OrderDate < '20170101'
 Group By
   Customers.CustomerID
   ,Customers.CompanyName
)
,CustomerGrouping as (
 Select
   CustomerID
   ,CompanyName
   ,TotalOrderAmount
   ,CustomerGroup =
     case
       when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
       when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
       when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
       when TotalOrderAmount >= 10000 then 'Very High'
    end
 from Orders2016
 -- Order by CustomerID
)
Select
 CustomerGroup
 , TotalInGroup = Count(*)
 , PercentageInGroup = Count(*) * 1.0/ (select count(*) from CustomerGrouping)
from CustomerGrouping
group by CustomerGroup
order by TotalInGroup desc

讨论

在答案中,我们添加了一个名为CustomerGrouping的中间CTE。CustomerGrouping被引用两次—— 一次是获取组中的客户总数,另一次是获得客户总数,作为百分比的分母。

请注意,在第二个CTE中的Order by CustomerID已经被注释掉了。如果你把它放在里面,你会得到错误。

51.灵活的客户分组

答案

;with Orders2016 as (
 Select
   Customers.CustomerID
   ,Customers.CompanyName
   ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
   Join Orders
     on Orders.CustomerID = Customers.CustomerID
   Join OrderDetails
     on Orders.OrderID = OrderDetails.OrderID
 Where
   OrderDate >= '20160101'
   and OrderDate < '20170101'
 Group by
   Customers.CustomerID
   ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroupName
from Orders2016
 Join CustomerGroupThresholds
   on Orders2016.TotalOrderAmount between
      CustomerGroupThresholds.RangeBottom and CustomerGroupThresholds.RangeTop
Order by CustomerID

讨论

请注意,这给出的结果与原来的问题相同。但是,不要使用Case语句中的硬编码值来定义CustomerGroups的边界,而是将它们放在表中。

这样做的好处是,你不需要在对客户进行分组的每个查询中重复以下代码,因为它是在表中定义的。

,CustomerGroup =
   case
     when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
     when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
     when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
     when TotalOrderAmount >= 10000 then 'Very High'
   end

另外,请看看CustomerGroupThresholds中的值。

select * From CustomerGroupThresholds

请注意,关于范围底部和范围顶部,这些行之间没有重叠。如果是Money之外的数据类型(小数点后4位),可能会有间隙或重叠。


未完待续

下一讲我们接着讨论剩余的高级问题。


如果喜欢这篇文章,请不要忘记关注🧡、点赞👍和收藏📔哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/707577.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++异常处理-漏洞利用

文章目录 参考异常处理顺序eh_frame段的作用编译过程中的.eh_frame生成运行时异常处理 堆栈展开简单劫持rbpret chop1. 异常发生时的堆栈保存2. 查找.eh_frame信息3. 解析FDE并恢复CFA4. 恢复寄存器5. 堆栈展开6. 转向异常处理逻辑 先忙awd了以后补 参考 https://xz.aliyun.co…

LeetCode刷题之HOT100之二叉树的遍历

2024/6/14 这几天总是下雨&#xff0c;天气预报上面显示这个月都要持续下雨&#xff0c;下雨天了怎么办&#xff1f;我好想你&#xff0c;不敢打给你&#xff0c;我找不到原因。说着说着唱起来了哈哈&#xff01;Anyway&#xff0c;昨天晚上打开了《涅朵奇卡一个女人的一生》&a…

Vue3:解决在main.ts 中调用自定义的js文件会报错的问题

案例&#xff1a;Vue3 &#xff0c;使用的是main.ts &#xff0c;在main.ts 中调用自定义的ruoComment.js文件会报错&#xff0c; 页面报错&#xff1a; main.ts文件引用报错&#xff1a; 解决报错&#xff1a;找到tsconfig.json文件 加上如下代码&#xff1a;即可解决问题 &q…

IDC最新报告,7大维度11家大模型厂商比拼,唯一全优是谁?

如果考试题太简单&#xff0c;学渣也能拿一百昏。在 AI 圈&#xff0c;我们应该拿怎样的「试卷」来检验一直处于流量 C 位的大模型的真实水平&#xff1f;是高考题吗&#xff1f;当然不是&#xff01; 也有些人认为&#xff0c;在各种 Benchmark 榜单上&#xff0c;谁排第一谁…

ai 人工智能免费网站免费生成图片生成ppt

豆包 Kimi.ai - 帮你看更大的世界 生成ppt 讯飞智文 - AI在线生成PPT、Word 大家如有其它免费的欢迎推荐!!!

动力学仿真平台:让模型配置与仿真测试更高效!

背景概述 动力学仿真平台是一种基于计算机技术的模拟工具&#xff0c;旨在模拟和分析物理系统中的动力学行为。通过建立数学模型&#xff0c;并借助高效的数值计算方法来模拟复杂系统的运动规律&#xff0c;为科研、设计、工程等领域提供重要的决策支持。动力学仿真平台的重要性…

图像算法之镜头畸变

桶形畸变&#xff08;Barrel Distortion&#xff09;&#xff1a; 桶形畸变是一种常见于广角镜头的畸变类型。在桶形畸变中&#xff0c;图像的中心区域被向外拉伸&#xff0c;使得直线在图像边缘部分显得向内弯曲&#xff0c;看起来像一个桶。这种畸变之所以发生&#xff0c;是…

Linux操作系统学习路线

本文来自Qwen2大模型&#xff1a; Linux操作系统的全面学习是一个渐进的过程&#xff0c;涵盖从基础知识到高级特性的多个阶段。以下是一份详细的Linux操作系统学习路线图&#xff0c;包括各个阶段的学习目标、建议的学习资源和实践步骤。 1. Linux 基础知识与安装 学习目标&a…

CD工具awx之清单Inventory,管理应用与主机的多对多关系

一、什么是清单 它决定的是一个应用部署到哪些目标机&#xff0c;清单管理的是应用&#xff08;组&#xff09;关联了哪些主机&#xff08;目标机&#xff09;。 1、新建清单 2、新建组 3、关联主机 新增主机或关联已有的主机 新主机 现有主机 服务关联主机完成&#xf…

ElementPlus国际化(将组件的默认语言改为中文)

文章目录 1. Element-plus的默认语言2. 编辑 main.js 文件3. 效果&#xff08;以分页条组件为例&#xff09; 1. Element-plus的默认语言 Element-plus的默认语言是英语&#xff0c;可修改为其它语言 2. 编辑 main.js 文件 import {createApp} from vue import ElementPlus …

deepin V23 RC2 正式发布!

deepin 是一款基于 Linux 的开源桌面操作系统&#xff0c;今天 deepin V23 RC2 正式发布&#xff0c;欢迎体验与反馈&#xff01;感谢每一位 deepiner 提供想法与建议&#xff0c;让我们一起为打造美观易用、安全可靠的开源操作系统而努力&#xff01; 【功能新增与优化】 新增…

电脑自带录屏在哪?电脑录屏,4个详细方法

在现代社会中&#xff0c;越来越多的人需要在电脑上录制视频&#xff0c;比如录制游戏操作、制作教学视频、演示文稿等等。因此&#xff0c;电脑录屏成为了一项非常重要的功能。那么电脑自带录屏在哪&#xff1f;本文将带领大家看看可以使用哪些方法进行录屏。 录屏方法一&…

CC攻击的有效应对方案

随着互联网的发展&#xff0c;网络安全问题愈发突出。CC攻击&#xff08;Challenge Collapsar Attack&#xff09;&#xff0c;一种针对Web应用程序的分布式拒绝服务&#xff08;DDoS&#xff09;攻击方式&#xff0c;已经成为许多网络管理员和网站拥有者不得不面对的重大挑战。…

什么?项目经理也算经理?

今天偶然看到一个有意思的问题&#xff1a;“如何破解项目经理的无权、无利、有责的现状”&#xff1f; 乍看有点费解&#xff0c;细想还挺有意思&#xff0c;这不禁引发了我的思考&#xff0c;项目经理到底算不算经理&#xff1f; 从管理学的角度来看&#xff0c;根据亨利法约…

电信网关配置管理系统 del_file.php 前台RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

笔记本电脑怎么连接无线网WiFi?4个连接方法分享!

“我新买了一台笔记本电脑&#xff0c;现在不知道怎么操作才能连接无线网。有朋友知道应该怎么操作吗&#xff1f;希望大家给我分享一下简单的方法。” 在数字化飞速发展的今天&#xff0c;笔记本电脑作为我们日常生活与工作中不可或缺的工具&#xff0c;其无线连接功能的重要性…

五分钟看完WWDC24

大家好&#xff0c;我是小编阿文。欢迎您关注我们&#xff0c;经常分享有关Android出海&#xff0c;iOS出海&#xff0c;App市场政策实时更新&#xff0c;互金市场投放策略&#xff0c;最新互金新闻资讯等文章&#xff0c;期待与您共航世界之海。 北京时间6月11日凌晨1点&…

智能化六面体大米装袋机:如何助力提升包装效率与质量

在快节奏的现代社会&#xff0c;高效、精准的包装设备对于提升大米产业的生产效率与产品质量至关重要。近年来&#xff0c;随着科技的不断进步&#xff0c;智能化六面体大米装袋机凭借其较好的性能和便捷的操作&#xff0c;逐渐成为大米加工企业的新宠。星派将深入探讨智能化六…

管理十大定律:深度解析与实际应用

在复杂多变的企业管理环境中&#xff0c;掌握并运用一些基本的定律和规律&#xff0c;对于提升管理效率、优化资源配置具有至关重要的作用。 1、马太效应 定律解析&#xff1a;马太效应描述了资源分配中的一种累积优势现象&#xff0c;即强者愈强&#xff0c;弱者愈弱。这源…

化学品危险性分类鉴定报告 危化品危险性分类

一、化学品危险性分类报告&#xff1a; 按照国务院令 第591号 《危险化学品安全管理条例》、原十部委公告 2015年 第5号 《危险化学品目录&#xff08;2015版&#xff09;》、原安监总局令 第60号《化学品物理危险性鉴定与分类管理办法》和原安监总局令 第53号《危险化学品登记…