SqlServer的实用且高级玩法.md
1.常见表表达式(CTEs)
如果您想要查询子查询,那就是CTEs施展身手的时候 - CTEs基本上创建了一个临时表。
使用常用表表达式(CTEs)是模块化和分解代码的好方法,与您将文章分解为几个段落的方式相同。
请在Where子句中使用子查询进行以下查询。
1.1 在查询中有许多子查询,那么怎么样?这就是CTEs发挥作用的地方。
---示例---
SELECT
name,
salary
FROM
People
WHERE
NAME IN ( SELECT DISTINCT NAME FROM population WHERE country = "Canada" AND city = "Toronto" )
AND salary >= (
SELECT
AVG( salary )
FROM
salaries
WHERE
gender = "Female")
---CTEs---
with toronto_ppl as (
SELECT DISTINCT name
FROM population
WHERE country = "Canada"
AND city = "Toronto"
)
, avg_female_salary as (
SELECT AVG(salary) as avgSalary
FROM salaries
WHERE gender = "Female"
)
SELECT name
, salary
FROM People
WHERE name in (SELECT DISTINCT FROM toronto_ppl)
AND salary >= (SELECT avgSalary FROM avg_female_salary)
现在很清楚,Where子句是在多伦多的名称中过滤。如果您注意到,CTE很有用,因为您可以将代码分解为较小的块,但它们也很有用,因为它允许您为每个CTE分配变量名称(即toronto_ppl和avg_female_salary) 同样,CTEs允许您完成更高级的技术,如创建递归表
2.临时函数
如果您想了解有关临时函数的更多信息,请检查此项,但知道如何编写临时功能是重要的原因:
- 它允许您将代码的块分解为较小的代码块
- 它适用于写入清洁代码
- 它可以防止重复,并允许您重用类似于使用Python中的函数的代码。
2.1 标量函数返回单个值,可以用于 SELECT 语句中的计算
SELECT name
, CASE WHEN tenure < 1 THEN "analyst"
WHEN tenure BETWEEN 1 and 3 THEN "associate"
WHEN tenure BETWEEN 3 and 5 THEN "senior"
WHEN tenure > 5 THEN "vp"
ELSE "n/a"
END AS seniority
FROM employees
-- 创建标量函数
CREATE FUNCTION dbo.MyTenureName
(
-- 参数列表
@Input int
)
RETURNS Nvarchar(255)
AS
BEGIN
-- 函数的逻辑
DECLARE @Result nvarchar(255);
-- 示例逻辑:将输入参数加倍
-- 使用 CASE 语句
SET @Result =
CASE
WHEN @Input < 1 THEN 'analyst'
WHEN @Input BETWEEN 1 and 3 THEN 'associate'
WHEN @Input BETWEEN 3 and 5 THEN 'senior'
WHEN @Input > 5 THEN 'vp'
ELSE 'n/a'
END;
RETURN @Result;
END;
-- 使用标量函数
SELECT name,tenure
,dbo.MyTenureName(tenure) as tenureName
FROM employees
2.2 创建表值函数(Table-Valued Function): 表值函数返回一个表,可以在 FROM 子句中用于查询。
-- 示例1
CREATE FUNCTION dbo.MyTableValuedFunction
(
-- 参数列表
@InputParameter INT
)
RETURNS TABLE
AS
RETURN (
-- 返回的表结构
SELECT
Column1,
Column2
FROM
YourTable
WHERE
SomeCondition = @InputParameter
);
-- 示例2
create function dbo.MyTableValuedFunction
(
-- 参数列表
@InputTopRow int = 10,
@InputName nvarchar(50) = ''
)
Returns Table
as
return (
SELECT top (@InputTopRow)
[name],
tenure,
CASE WHEN tenure < 1 THEN 'analyst'
WHEN tenure BETWEEN 1 and 3 THEN 'associate'
WHEN tenure BETWEEN 3 and 5 THEN 'senior'
WHEN tenure > 5 THEN 'vp'
ELSE 'n/a'
END AS seniority
FROM employees where [name] like '%'+ISNULL(@InputName,'')+'%')
)
-- 使用表值函数
select * from MyTableValuedFunction(5,'张三')
2.3 删除函数
-- 删除标量函数
DROP FUNCTION dbo.MyScalarFunction;
-- 删除表值函数
DROP FUNCTION dbo.MyTableValuedFunction;
3.使用CASE WHEN枢转数据
您很可能会看到许多要求在陈述时使用CASE WHEN的问题,这只是因为它是一种多功能的概念。如果要根据其他变量分配某个值或类,则允许您编写复杂的条件语句。较少众所周知,它还允许您枢转数据。例如,如果您有一个月列,并且您希望为每个月创建一个单个列,则可以使用语句追溯数据的情况。
示例问题:编写SQL查询以重新格式化表,以便每个月有一个收入列
-- 创建表
CREATE TABLE Case_Test_Table (
id INT,
revenue INT,
month VARCHAR(3)
);
-- 插入数据
INSERT INTO Case_Test_Table (id, revenue, month)
VALUES
(1, 8000, 'Jan'),
(2, 9000, 'Jan'),
(3, 10000, 'Feb'),
(1, 7000, 'Feb'),
(1, 6000, 'Mar');
Initial table:
+------+---------+-------+
| id | revenue | month |
+------+---------+-------+
| 1 | 8000 | Jan |
| 2 | 9000 | Jan |
| 3 | 10000 | Feb |
| 1 | 7000 | Feb |
| 1 | 6000 | Mar |
+------+---------+-------+
Result table:
+------+-------------+-------------+-------------+-----+-----------+
| id | Jan_Revenue | Feb_Revenue | Mar_Revenue | ... | Dec_Revenue |
+------+-------------+-------------+-------------+-----+-----------+
| 1 | 8000 | 7000 | 6000 | ... | null |
| 2 | 9000 | null | null | ... | null |
| 3 | null | 10000 | null | ... | null |
+------+-------------+-------------+-------------+-----+-----------+
-- 结果示例 Sql
SELECT
id,
MAX(CASE WHEN month = 'Jan' THEN revenue END) AS Jan_Revenue,
MAX(CASE WHEN month = 'Feb' THEN revenue END) AS Feb_Revenue,
MAX(CASE WHEN month = 'Mar' THEN revenue END) AS Mar_Revenue,
MAX(CASE WHEN month = 'Apr' THEN revenue END) AS Apr_Revenue,
MAX(CASE WHEN month = 'May' THEN revenue END) AS May_Revenue,
MAX(CASE WHEN month = 'Jun' THEN revenue END) AS Jun_Revenue,
MAX(CASE WHEN month = 'Jul' THEN revenue END) AS Jul_Revenue,
MAX(CASE WHEN month = 'Aug' THEN revenue END) AS Aug_Revenue,
MAX(CASE WHEN month = 'Sep' THEN revenue END) AS Sep_Revenue,
MAX(CASE WHEN month = 'Oct' THEN revenue END) AS Oct_Revenue,
MAX(CASE WHEN month = 'Nov' THEN revenue END) AS Nov_Revenue,
MAX(CASE WHEN month = 'Dec' THEN revenue END) AS Dec_Revenue
FROM Case_Test_Table
GROUP BY id
ORDER BY id;
4.EXCEPT vs NOT IN 差异
EXCEPT 和 NOT IN 都是用于从查询结果中排除特定值的 SQL 查询语句的部分。然而,它们有一些关键的差异:
- 语法结构:
EXCEPT使用两个 SELECT 语句,它从第一个查询的结果中排除第二个查询的结果。NOT IN在单个 SELECT 语句中使用,并且通常结合子查询来排除特定值。
- 处理 NULL 值:
EXCEPT会自动处理 NULL 值。如果两个查询中都有 NULL 值,它们将被视为相等,不会被排除。NOT IN在比较中对 NULL 值的处理可能不同,具体取决于数据库的实现。通常情况下,NOT IN可能需要特殊处理 NULL。
- 性能:
- 在某些情况下,数据库引擎可能对
EXCEPT优化得更好,尤其是当查询中包含大量结果时。 NOT IN的性能可能受到查询中值的数量和索引的影响。
- 在某些情况下,数据库引擎可能对
- 查询结果:
EXCEPT返回两个查询结果的差异,即从第一个结果中排除了第二个结果。NOT IN返回满足条件的所有行,除了子查询中指定的值。
以下是示例说明:
使用 EXCEPT 的示例:
SELECT column1 FROM table1
EXCEPT
SELECT column1 FROM table2;
使用 NOT IN 的示例:
SELECT column1 FROM table1
WHERE column1 NOT IN (SELECT column1 FROM table2);
总体而言,选择使用 EXCEPT 还是 NOT IN 取决于具体的查询需求和对 NULL 值的处理偏好。
5.自联结
一个SQL表自行连接自己。你可能会认为没有用,但你会感到惊讶的是这是多么常见。在许多现实生活中,数据存储在一个大型表中而不是许多较小的表中。在这种情况下,可能需要自我连接来解决独特的问题。
让我们来看看一个例子。
示例问题:给定下面的员工表,写出一个SQL查询,了解员工的工资,这些员工比其管理人员工资更多。对于上表来说,Joe是唯一一个比他的经理工资更多的员工。
CREATE TABLE YourTable (
Id INT,
Name VARCHAR(50),
Salary INT,
ManagerId INT
);
INSERT INTO YourTable (Id, Name, Salary, ManagerId)
VALUES
(1, 'Joe', 70000, 3),
(2, 'Henry', 80000, 4),
(3, 'Sam', 60000, NULL),
(4, 'Max', 90000, NULL);
+----+-------+--------+-----------+
| Id | Name | Salary | ManagerId |
+----+-------+--------+-----------+
| 1 | Joe | 70000 | 3 |
| 2 | Henry | 80000 | 4 |
| 3 | Sam | 60000 | NULL |
| 4 | Max | 90000 | NULL |
+----+-------+--------+-----------+Answer:
SELECT
a.Name as Employee
FROM
Employee as a
JOIN Employee as b on a.ManagerID = b.Id
WHERE a.Salary > b.Salary
6. Rank vs Dense Rank vs Row Number
6.1.ROW_NUMBER() OVER (ORDER BY GPA desc)
6.2 RANK() OVER (ORDER BY GPA desc)
6.3 DENSE_RANK() OVER (ORDER BY GPA desc)
这些都是用于在 SQL 中进行排名(ranking)的窗口函数。它们通常与 OVER 子句一起使用,用于根据指定的排序条件对结果集中的行进行排名。
- ROW_NUMBER() OVER (ORDER BY GPA desc):
ROW_NUMBER()分配唯一的整数值给结果集中的每一行,按照指定的排序条件(这里是GPA降序)进行排序。即,每行都有一个唯一的排名,不会有相同的排名。- 例如,如果有两个相同的 GPA,它们将被分配不同的
ROW_NUMBER()。
- RANK() OVER (ORDER BY GPA desc):
RANK()为每一行分配一个排名,但允许有相同的排名。如果两个行具有相同的排序条件(GPA),它们将被分配相同的排名,并且下一个排名将被跳过。- 例如,如果两个相同的 GPA,它们将被分配相同的
RANK(),下一个行将被跳过。
- DENSE_RANK() OVER (ORDER BY GPA desc):
DENSE_RANK()类似于RANK(),也为每一行分配一个排名。然而,不同之处在于它不会跳过排名。即,如果有两个行具有相同的排序条件(GPA),它们将被分配相同的排名,并且下一个排名不会被跳过。- 例如,如果两个相同的 GPA,它们将被分配相同的
DENSE_RANK(),下一个行将被继续分配下一个排名。
这些排名函数通常用于在查询结果中创建排名列,以便更容易了解每行在排序中的位置。
7. OVER 窗口函数
OVER 子句通常与窗口函数一起使用,用于定义窗口(window),指定在执行窗口函数时要考虑的行的范围。OVER 子句的主要作用是控制窗口函数的计算范围,从而提供更灵活的查询和分析能力。以下是一些常见的用法:
CREATE TABLE YourTable (
column1 INT,
column2 INT,
column3 INT
);
INSERT INTO YourTable (column1, column2, column3)
VALUES
(1, 10, 100),
(2, 20, 200),
(3, 30, 300),
(4, 40, 400),
(5, 50, 500);
ORDER BY 子句:
OVER子句通常包含ORDER BY子句,用于指定窗口函数计算时的排序条件。这可以确保在窗口函数中按照指定的顺序处理数据。
sqlCopy codeSELECT
column1,
column2,
SUM(column3) OVER (ORDER BY column1) AS RunningTotal
FROM
YourTable;
PARTITION BY 子句:
OVER子句还可以包含PARTITION BY子句,用于将数据分成逻辑上的分区,窗口函数在每个分区内进行计算。这允许在分组级别上执行窗口函数。
sqlCopy codeSELECT
column1,
column2,
AVG(column3) OVER (PARTITION BY column1) AS AvgInPartition
FROM
YourTable;
ROWS 或 RANGE 子句:
OVER子句还可以包含ROWS或RANGE子句,用于指定窗口的实际行范围。这允许定义窗口函数计算时要考虑的具体行数或范围。
sqlCopy codeSELECT
column1,
column2,
SUM(column3) OVER (ORDER BY column1 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS MovingSum
FROM
YourTable;
UNBOUNDED 子句:
OVER子句还可以使用UNBOUNDED关键字,用于表示窗口的边界不受限制。
sqlCopy codeSELECT
column1,
column2,
SUM(column3) OVER (ORDER BY column1 ROWS UNBOUNDED PRECEDING) AS CumulativeSum
FROM
YourTable;
通过结合 OVER 子句和不同的窗口函数,可以实现各种复杂的分析和聚合操作
8.计算Delta值
另一个常见应用程序是将不同时期的值进行比较。例如,本月和上个月的销售之间的三角洲是什么?或者本月和本月去年这个月是什么?
在将不同时段的值进行比较以计算Deltas时,这是Lead()和LAG()发挥作用时。
这是一些例子:
# Comparing each month's sales to last month
SELECT month
, sales
, sales - LAG(sales, 1) OVER (ORDER BY month)
FROM monthly_sales
# Comparing each month's sales to the same month last year
SELECT month
, sales
, sales - LAG(sales, 12) OVER (ORDER BY month)
FROM monthly_sales
9.计算运行总数
如果你知道关于row_number()和lag()/ lead(),这可能对您来说可能不会惊喜。但如果你没有,这可能是最有用的窗口功能之一,特别是当您想要可视化增长!
使用具有SUM()的窗口函数,我们可以计算运行总数。请参阅下面的示例:
SELECT Month
, Revenue
, SUM(Revenue) OVER (ORDER BY Month) AS Cumulative
FROM monthly_revenue
10.日期时间操纵
您应该肯定会期望某种涉及日期时间数据的SQL问题。例如,您可能需要将数据分组组或将可变格式从DD-MM-Yyyy转换为简单的月份。
您应该知道的一些功能是:
- 提炼
- 日元
- date_add,date_sub.
- date_trunc.
示例问题:给定天气表,写一个SQL查询,以查找与其上一个(昨天)日期相比的温度较高的所有日期的ID。
+---------+------------------+------------------+
| Id(INT) | RecordDate(DATE) | Temperature(INT) |
+---------+------------------+------------------+
| 1 | 2015-01-01 | 10 |
| 2 | 2015-01-02 | 25 |
| 3 | 2015-01-03 | 20 |
| 4 | 2015-01-04 | 30 |
+---------+------------------+------------------+Answer:
SELECT
a.Id
FROM
Weather a,
Weather b
WHERE
a.Temperature > b.Temperature
AND DATEDIFF(a.RecordDate, b.RecordDate) = 1
SqlServer的实用且高级玩法.md的更多相关文章
- maven 高级玩法
maven 高级玩法 标签(空格分隔): maven 实用技巧 Maven 提速 多线程 # 用 4 个线程构建,以及根据 CPU 核数每个核分配 1 个线程进行构建 $ mvn -T 4 clean ...
- 轻量级高性能ORM框架:Dapper高级玩法
Dapper高级玩法1: 数据库中带下划线的表字段自动匹配无下划线的Model字段. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 备 ...
- 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类
依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...
- 【Python基础】random 的高级玩法
random 模块的高级玩法 1.python 随机产生姓名 方式一: import random xing = [ '赵', '钱', '孙', '李', '周', '吴', '郑', '王', ' ...
- Word 查找替换高级玩法系列之 -- 段首批量添加字符
打开「查找和替换」输入框,按照下图操作: 更多查找替换高级玩法,参看:Word查找替换高级玩法系列 -- 目录篇 未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)
- Word 查找替换高级玩法系列之 -- 把论文中的缩写词快速变成目录下边的注释表
1. 前言 问题:Word写论文如何把文中的缩写快速转换成注释表? 原来样子: 想要的样子: 2. 步骤 使用查找替换高级用法,替换缩写顺序 选中所有文字 打开查找替换对话框,输入以下表达式: 替换后 ...
- 十五天精通WCF——第九天 高级玩法之自定义Behavior
终于我又看完了二期爱情保卫战,太酸爽了,推荐链接:http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd,不多说,谁看谁入迷,下面言归正传, 看看这 ...
- [转]十五天精通WCF——第九天 高级玩法之自定义Behavior
终于我又看完了二期爱情保卫战,太酸爽了,推荐链接:http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd,不多说,谁看谁入迷,下面言归正传, 看看这 ...
- GoldenDict词典的超级实用高级玩法----全文搜索功能
快捷键: Ctrl+Shift+F 菜单进入:搜索--全文搜索 模式:正则表达式 比如:我想知道地道的英文表达 请xx天/周/年假 给搜索框写入正则表达式 请(.)(天|周|年)假 就可以了 ...
- awk高级玩法
1. 程序元素 一个awk 程序是一对以模式(pattern) 与大括号框起来的操作(action) 组合而成的,或许,还会加上实现操作细节的函数(function ) .针对每个匹配于输人数据的模式 ...
随机推荐
- python3发送需要双向认证的wss请求
python3发送需要双向认证的wss请求 websocket链接python有很多封装好的库:websocket-client.websockets.aiowebsocket 这里用的websoke ...
- django学习第四天----mark_safe的用法,静态文件配置,用指令创建django项目应用注意点,ORM介绍,创建表执行命令,模板渲染补充(组件),inclusion_tag 自定义标签
补充第三天跟safe差不多的一个方法 templatetags文件夹 自定义的py文件 需要先导入模块 from django.utils.safestring import mark_safe @r ...
- 前后端分离解决跨域cors问题
修改windows的hosts文件 vim C:\Windows\System32\drivers\etc\hosts 添加域名 前端:www.luffycity.cn 后端:api.luffycit ...
- 面向对象基础---day02
成员变量和局部变量区别 封装 private关键字 1.是一个权限修饰符 2.可以修饰成员(成员变量和成员方法) 3.作用是保护成员不被别的类使用,被private修饰的成员只在本类中才能访问 针对p ...
- CT图像重建
20世纪70年代中期,在医学领域出现了一种神奇装置,名为"计算机辅助 X 射线断层成像仪"(简称CAT或CT),它能够在不损伤病人的情况下,提供人体从头到脚各部位的断层X射线图像. ...
- 图查询语言 nGQL 简明教程 vol.01 快速入门
本文旨在让新手快速了解 nGQL,掌握方向,之后可以脚踩在地上借助文档写出任何心中的 NebulaGraph 图查询. 视频 本教程的视频版在B站这里. 准备工作 在正式开始 nGQL 实操之前,记得 ...
- 黑马python基础课的一些题
1, 打印5行小星星 思路: 可以用1个星星乘以行数:还可以循环嵌套,外层循环控制行数,内层循环控制每一行应该输出多少个小星星,比如,第一行输出1个,第二行输出2个,内层循环可以当成列,只不过这个列要 ...
- 二十: MySql 事务日志
MySql 事务日志 事务有4种特性:原子性.一致性.隔离性和持久性.那么事务的四种特性到底是基于什么机制实现呢? 事务的隔离性由 锁机制 实现. 而事务的原子性.一致性和持久性由事务的 redo 日 ...
- C++ //内建函数对象 算数仿函数 关系仿函数 //逻辑仿函数
1 //内建函数对象 算数仿函数 关系仿函数 //逻辑仿函数 2 #include<iostream> 3 #include<string> 4 #include<fun ...
- Jmeter+Influxdb+Grafana搭建
背景 在无界面压测情况下,我们需要去额外搭建可视化观测平台.借助于Influxdb+Grafana,我们可以轻松让Jmeter的结果自动写入Influxdb,Influxdb实时存储运行结果,最后由G ...