【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个的过滤器。

SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)
From CustomersJoin Orderson Orders.CustomerID = Customers.CustomerIDJoin OrderDetailson Orders.OrderID = OrderDetails.OrderID
WhereOrderDate >= '20160101'and OrderDate < '20170101'
Group ByCustomers.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语句

SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)
From Customersjoin Orderson Orders.CustomerID = Customers.CustomerIDjoin OrderDetailson Orders.OrderID = OrderDetails.OrderID
WhereOrderDate >= '20160101'and OrderDate < '20170101'
Group ByCustomers.CustomerID,Customers.CompanyName

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


答案

48.客户分组

答案

;with Orders2016 as (SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)From CustomersJoin Orderson Orders.CustomerID = Customers.CustomerIDJoin OrderDetailson Orders.OrderID = OrderDetails.OrderIDWhereOrderDate >= '20160101'and OrderDate < '20170101'Group byCustomers.CustomerID,Customers.CompanyName
)
SelectCustomerID,CompanyName,TotalOrderAmount,CustomerGroup =Casewhen 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:

SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice),CustomerGroup =Casewhen 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 CustomersJoin Orderson Orders.CustomerID = Customers.CustomerIDJoin OrderDetailson Orders.OrderID = OrderDetails.OrderID
WhereOrderDate >= '20160101'and OrderDate < '20170101'
Group ByCustomers.CustomerID,Customers.CompanyName

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

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

49.客户分组-修复null

答案

;with Orders2016 as (SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)From CustomersJoin Orderson Orders.CustomerID = Customers.CustomerIDJoin OrderDetailson Orders.OrderID = OrderDetails.OrderIDWhereOrderDate >= '20160101'and OrderDate < '20170101'Group byCustomers.CustomerID,Customers.CompanyName
)
SelectCustomerID,CompanyName,TotalOrderAmount,CustomerGroup =casewhen 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 (SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)From Customersjoin Orderson Orders.CustomerID = Customers.CustomerIDjoin OrderDetailson Orders.OrderID = OrderDetails.OrderIDWhereOrderDate >= '20160101'and OrderDate < '20170101'Group ByCustomers.CustomerID,Customers.CompanyName
)
,CustomerGrouping as (SelectCustomerID,CompanyName,TotalOrderAmount,CustomerGroup =casewhen 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'endfrom Orders2016-- Order by CustomerID
)
SelectCustomerGroup, 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 (SelectCustomers.CustomerID,Customers.CompanyName,TotalOrderAmount = SUM(Quantity * UnitPrice)From CustomersJoin Orderson Orders.CustomerID = Customers.CustomerIDJoin OrderDetailson Orders.OrderID = OrderDetails.OrderIDWhereOrderDate >= '20160101'and OrderDate < '20170101'Group byCustomers.CustomerID,Customers.CompanyName
)
SelectCustomerID,CompanyName,TotalOrderAmount,CustomerGroupName
from Orders2016Join CustomerGroupThresholdson Orders2016.TotalOrderAmount betweenCustomerGroupThresholds.RangeBottom and CustomerGroupThresholds.RangeTop
Order by CustomerID

讨论

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

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

,CustomerGroup =casewhen 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位),可能会有间隙或重叠。


未完待续

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


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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS

文章汇总 总体来看像是一种带权重的残差&#xff0c;但解决的如何高效问题的事情。 相比模型的全微调&#xff0c;作者提出固定预训练模型参数不变&#xff0c;在原本权重矩阵旁路添加低秩矩阵的乘积作为可训练参数&#xff0c;用以模拟参数的变化量。 模型架构 h W 0 x △…

31、shell循环

一、循环 循环&#xff1a;循环是一种重复执行一段代码的结构。只要满足循环的条件&#xff0c;会一直执行这个代码。 循环条件&#xff1a;在一定范围之内&#xff0c;按照指定的次数来执行循环。 循环体&#xff1a;在指定的次数内&#xff0c;执行的命令序列。只要条件满…

深入解析 Spring Cloud Seata:分布式事务的全面指南

&#x1f9e8;&#x1f9e8;&#x1f9e8;深入解析 Spring Cloud Seata&#xff1a;分布式事务的全面指南 在微服务架构中&#xff0c;分布式事务的处理是一项复杂而重要的任务。Spring Cloud Seata 是一款专为分布式事务而设计的解决方案&#xff0c;它由阿里巴巴开源&#x…

宏电“灌区哨兵”助力灌区信息化建设,开启灌区“智水”时代

灌区是保障国家粮食安全的重要水利设施。“十四五”提出&#xff0c;要推进大中型灌区节水改造和精细化管理。灌区信息化是建设智慧水利、深化行业监管、提升灌区科学管理水平的基础支撑&#xff0c;也是“十四五”期间灌区现代化改造的重点内容之一。 宏电智慧灌区信息化解决方…

2024脑卒中评估量表分享

常笑医学整理了5个常用的脑卒中评估量表&#xff0c;供临床医护工作人员参考。 Essen脑卒中风险评分量表-常笑医学网​ &#xff08;完整量表请点击量表名称查看&#xff09; Essen脑卒中风险评估量表&#xff0c;是一个简便、易于临床操作的9分量表&#xff0c;是根据氯吡格雷…

k8s nginx.conf配置文件配置

无状态nginx配置nginx.conf覆盖容器配置nginx.conf 代码&#xff1a;events {worker_connections 1024; }http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main $remote_addr - $remote_user [$time_local] "$request&q…

reGeorg隐秘隧道搭建

reGeorg隐秘隧道搭建 【实验目的】 通过学习reGeorg与Proxifier工具使用&#xff0c;实现外网攻击端连接内网主机远程桌面。 【知识点】 python、reGeorg、proxifier。 【实验原理】 在内网渗透中&#xff0c;由于防火墙的存在&#xff0c;导致无法对内网直接发起连接&#xff…

Linux多线程编程中的同步与互斥

文章目录 一、线程同步与互斥1、理解线程同步2、互斥的概念3、小结 二、互斥锁&#xff08;Mutex&#xff09;1、互斥锁的定义和作用2、pthread库中的互斥锁3、互斥锁的实现原理4、示例代码演示互斥锁的基本用法 三、条件变量&#xff08;Condition Variable&#xff09;1、条件…

IDEA 配置方法模板无法获取到参数值和返回值(methodParameters()、methodReturnType()获取不到值)

问题现象&#xff1a; 我在 review 同事代码时候&#xff0c;发现方法上有注释&#xff0c;但是注释上又没有方法参数和返回值&#xff0c;这不是IDEA 配置了方法模板就可以自动生成的嘛&#xff0c;我出于好奇去问了下该同事是怎么回事&#xff0c;该同事有点不好意思的说我配…

昂辉科技EasySAR-BootLoader上位机产品

近年来&#xff0c;硬件标准化、同质化和软件差异化、复杂化成为了汽车产品研发的重要趋势。与此同时&#xff0c;大量的智能化功能和快速上车的节奏&#xff0c;对软件开发提出了更高的要求。在软硬件解耦的大背景下&#xff0c;建立统一的软件体系和开发工具以紧跟硬件更新迭…

【NOI-题解】1389 - 数据分析1750 - 有0的数1457 - 子数整除1121 - “倒”数1962. 数值计算

文章目录 一、前言二、问题问题&#xff1a;1389 - 数据分析问题&#xff1a;1750 - 有0的数问题&#xff1a;1457 - 子数整除问题&#xff1a;1121 - “倒”数问题&#xff1a;1962. 数值计算 三、感谢 一、前言 本章节主要对循环中带余除法部分题目进行讲解&#xff0c;包括…

python数据分析-北京市二手住宅市场价格波动分析

一、研究背景&#xff1a; 北京市作为中国的首都和经济中心&#xff0c;房地产市场一直备受关注。二手住宅市场是房地产市场的重要组成部分&#xff0c;其价格波动不仅影响着购房者和卖房者的利益&#xff0c;也对整个经济社会的稳定和发展产生重要影响。因此&#xff0c;对北…

idea 配置文件中文乱码

再进行springboot项目开发时发现新建的配置文件中文注释乱码&#xff0c;如下: 处理办法: 1、打开idea&#xff0c;在 File 中找到 Settings,如下图 2、搜索 encodings 找到 File Encodings&#xff0c;如下图 3、将上图中圈上的地方全部改为 UTF-8 编码最后点击 Apply 应用即…

大数据同步方案怎么选,才能提高企业的业务效率?

大数据同步通常指的是在多个数据源或存储系统之间同步数据的过程&#xff0c;可以确保数据的一致性&#xff0c;提高数据的可用性和可靠性&#xff0c;同时支持数据分析和决策制定。 大数据同步的步骤通常包括&#xff1a; 数据识别&#xff1a;确定需要同步的数据类型和范围&…

爬虫-模拟登陆博客

import requests from bs4 import BeautifulSoupheaders {user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 } # 登录参数 login_data {log: codetime,pwd: shanbay520,wp-submit: …

eBay测评,自养号应该如何做?

测评自养号就是自己搭建国外的服务器和IP环境&#xff0c;实现自己注册eBay的买家账号&#xff0c;通过电脑端环境一台电脑就可以无限养号&#xff0c;一次可以开十几个窗口同时浏览下单&#xff0c;每个窗口都是独立的环境&#xff0c;一账号一环境一IP一卡 买家账号掌握在卖…

酷开科技丨酷开系统智慧中心,解锁AI智能家居生活的无限可能

想象一下&#xff0c;未来的AI电视不再是冷冰冰的机器&#xff0c;而是家庭的智能伙伴。它学习你的喜好&#xff0c;预测你的需求&#xff0c;用声音和触感与你交流。它控制家中的灯光、温度&#xff0c;甚至帮你订购生活用品。 在探索智能家居的未来发展时&#xff0c;酷开系…

Day01 数据结构概述

目录 一、数据结构概述 1、基本概念 2、数据结构 3、逻辑关系&#xff08;线性结构&非线性结构&#xff09; 4、物理结构&#xff08;存储结构&#xff09; 5、算法 6、算法特征 二、时空复杂度 1、时间复杂度 2、空间复杂度 3、结构类型 一、数据结构概述 1、…

FullCalendar日历组件集成实战(12)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

记Windows环境下JDK安装配置

写在文章开头 这是笔者非常早期接触Java时写的文章&#xff0c;为方便每次系统重装时能够快速完成JDK解压版安装配置遂用此文记录了一下整个过程。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff0c;是 CSDN的博客专家 &#x…