SQL练习记录

99 阅读4分钟

select 语句执行优先级

AND 优先级高于 OR

 -- 示例
 SELECT *
 FROM trx_rcd
 WHERE 
     mch_typ = '餐饮' OR mch_typ = '休闲娱乐' AND trx_amt > 900;
 /**
 运行时实际的评估顺序是:
     1.mch_typ = '休闲娱乐' AND trx_amt > 900 会先被计算
     2.然后结果会与 mch_typ = '餐饮' 进行 OR 运算
 */
 -- 实际运行时语句为:
 SELECT *
 FROM trx_rcd
 WHERE 
     mch_typ = '餐饮' OR (mch_typ = '休闲娱乐' AND trx_amt > 900);
     
 -- 若想先判断 "mch_typ = '餐饮' OR mch_typ = '休闲娱乐'",需要将语句修改为:
 SELECT *
 FROM trx_rcd
 WHERE 
     (mch_typ = '餐饮' OR mch_typ = '休闲娱乐') AND trx_amt > 900;

日期函数

DATE_FORMAT:格式化日期、时间值

 -- 函数介绍
 -- date: 要格式化的日期或时间值,可以是一个列名、一个字符串或一个日期时间表达式。
 -- format: 一个字符串,定义了日期或时间的输出格式
 DATE_FORMAT(date, format)
 ​
 -- format 字符串可以包含多种格式化符号,常见的有:
 -- %Y: 四位年份(如 2023)
 -- %m: 两位月份(01 到 12)
 -- %d: 两位日期(01 到 31)
 -- %H: 两位小时(00 到 23)
 -- %i: 两位分钟(00 到 59)
 -- %s: 两位秒钟(00 到 59)
 -- 示例:按 "年-月-日" 格式输出
 SELECT DATE_FORMAT('2023-09-07', '%Y-%m-%d') AS formatted_date;
 ​
 -- 输出
 formatted_date|
 --------------+
 2023-09-07    |
 ​
 -- 示例:分别提取年、月、日、时、分、秒
 SELECT DATE_FORMAT('2023-09-07 14:30:00', '%Y,%m,%d,%H,%i,%s') AS formatted_datetime;
 ​
 -- 输出
 formatted_datetime |
 -------------------+
 2023,09,07,14,30,00|

DATEDIFF:计算两个日期之间的天数差

 -- 函数介绍
 -- 用于计算两个日期之间的天数差
 -- date1: 第一个日期,通常是结束日期
 -- date2: 第二个日期,通常是开始日期
 DATEDIFF(date1, date2)
 ​
 -- 返回一个整数,表示 date1 和 date2 之间的天数差
 -- 如果 date1 在 date2 之前,返回的值为负数
 -- 示例:计算 当前日期 与 2023-09-30 之间的天数差
 SELECT 
     DATEDIFF('2023-09-30', NOW()) AS `date1 早于 date2`,
     DATEDIFF(NOW(), '2023-09-30') AS `date1 晚于 date2`;
 ​
 -- 输出
 date1 早于 date2|date1 晚于 date2|
 ----------------+----------------+
           -343  |            343|

窗口函数

lag()、lead()

函数介绍

lag、lead可以简单看做是相反功能的窗口函数

  • lag:主要用于在查询结果集中获取当前行的前几行的数据。
 -- 语法
 LAG(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY order_column)
 ​
 -- 参数解释
 -- column_name: 要获取行值的列名。
 -- offset: 可选参数,指定要向上偏移的行数(默认值为 1)。
 -- default_value: 可选参数,当没有前几行时返回的默认值(如果不指定,则返回 NULL)。
 -- PARTITION BY: 可选参数,用于将结果集划分为多个部分,LAG 函数将在每个部分内独立工作。
 -- ORDER BY: 必须指定,用于定义窗口内行的顺序。
  • lead:用于在查询结果集中获取当前行的后几行的数据。
 -- 语法
 LEAD(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY order_column)
 ​
 -- 参数解释
 -- column_name: 要获取行值的列名。
 -- offset: 可选参数,指定要向下偏移的行数(默认值为 1)。
 -- default_value: 可选参数,当没有后几行时返回的默认值(如果不指定,则返回 NULL)。
 -- PARTITION BY: 可选参数,用于将结果集划分为多个部分,LEAD 函数将在每个部分内独立工作。
 -- ORDER BY: 必须指定,用于定义窗口内行的顺序。

题目来源

180. 连续出现的数字 - 力扣(高频 SQL 50 题(基础版))

题目

 表:Logs
 +-------------+---------+
 | Column Name | Type    |
 +-------------+---------+
 | id          | int     |
 | num         | varchar |
 +-------------+---------+
 在 SQL 中,id 是该表的主键。
 id 是一个自增列。
  
 找出所有至少连续出现三次的数字。
 返回的结果表中的数据可以按 任意顺序 排列。
 结果格式如下面的例子所示:
 ​
 示例 1:
 输入:
 Logs 表:
 +----+-----+
 | id | num |
 +----+-----+
 | 1  | 1   |
 | 2  | 1   |
 | 3  | 1   |
 | 4  | 2   |
 | 5  | 1   |
 | 6  | 2   |
 | 7  | 2   |
 +----+-----+
 ​
 输出:
 Result 表:
 +-----------------+
 | ConsecutiveNums |
 +-----------------+
 | 1               |
 +-----------------+
 解释:1 是唯一连续出现至少三次的数字。

解法一(lag + lag)

 select 
     num,
     -- num列向上偏移一行
     lag(num,1) over (order by id) num1,
     -- num列向上偏移两行
     lag(num,2) over (order by id) num2
 from
 Logs
 ​
 -- 输出
 -- num、num1、num2三列数值相同,则代表一个数字连续出现三次
 | num | num1 | num2 |
 | --- | ---- | ---- |
 | 1   | null | null |
 | 1   | 1    | null |
 | 1   | 1    | 1    |
 | 2   | 1    | 1    |
 | 1   | 2    | 1    |
 | 2   | 1    | 2    |
 | 2   | 2    | 1    |
 select
     num ConsecutiveNums
 from
     (select 
             num,
             lag(num,1) over (order by id) num1,
             lag(num,2) over (order by id) num2
      from
      Logs)t 
 where t.num = t.num1 AND t.num = t.num2
 ​
 -- 输出
 | ConsecutiveNums |
 | --------------- |
 | 1               |

解法二(lag + lead)

 select 
     num,
     -- num列向上偏移一行
     lag(num,1) over (order by id) num1,
     -- num列向下偏移一行
     lead(num,1) over (order by id) num2
 from
 Logs
 ​
 -- 输出
 -- num、num1、num2三列数值相同,则代表一个数字连续出现三次
 | num | num1 | num2 |
 | --- | ---- | ---- |
 | 1   | null | 1    |
 | 1   | 1    | 1    |
 | 1   | 1    | 2    |
 | 2   | 1    | 1    |
 | 1   | 2    | 2    |
 | 2   | 1    | 2    |
 | 2   | 2    | null |
 select
     num ConsecutiveNums
 from
     (select 
             num,
             lag(num,1) over (order by id) num1,
             lead(num,1) over (order by id) num2
      from
      Logs)t 
 where t.num = t.num1 AND t.num = t.num2
 ​
 -- 输出
 | ConsecutiveNums |
 | --------------- |
 | 1               |