评论

收藏

[SQL Server] 数据库之SQL技巧整理案例

数据库 数据库 发布于:2021-08-03 12:13 | 阅读数:258 | 评论:0

一、获得给定月份的周日数
根据给定的某个日期,计算这个月份的周日的天数。
根据系统变量@@DATEFIRST的值,判断周日的序号为【DatePart(WEEKDAY,RQ)= (07-@@DateFirst) % 7 + 1】。下面列出了周日、周一…周六的公式
公式
周几
(7-@@DateFirst)%7 +1
周日
(7-@@DateFirst)%7 +2
周一
(7-@@DateFirst)%7 +3
周二
(7-@@DateFirst)%7 +4
周三
(7-@@DateFirst)%7 +5
周四
(7-@@DateFirst)%7 +6
周五
(7-@@DateFirst)%7 +7
周六

下面是获得周日的SQL语句,SQL语句采用了嵌套循环的方式来获取数据

DECLARE @Day SmallDateTime
SET @Day = DateAdd(MM, DateDiff(MM,0,'2019-11-21'), 0)

;WITH Temp AS
(  SELECT @Day AS RQ UNION ALL
  SELECT RQ+1
  FROM TEMP WHERE DateDiff(Month,RQ+1,@Day) = 0
)
SELECT
  RN = Row_Number() Over(ORDER BY RQ),
  RQ
FROM Temp WHERE DatePart(WEEKDAY,RQ)= (07-@@DateFirst) % 7 + 1
其中:
【DateAdd(MM, DateDiff(MM,0,‘2019-08-21'), 0)】是获取当月第一天的通常做法
运行结果如下:
DECLARE @RQ SMALLDATETIME
SET @RQ = '2019-09-01';

;WITH
  tAppDays (fDay) AS
  (
  SELECT @RQ AS fDay
  UNION ALL
  SELECT fDay + 1 FROM tAppDays WHERE DateDiff(Month,fDay+1,@RQ) = 0
  )
SELECT * FROM tAppDays ORDER BY fDAY
二、获得给定月份的所有天的日期
其中:
【DateDiff(Month,fDay+1,@RQ) = 0】是判断月份相等的通常做法
DECLARE @RQ SMALLDATETIME
SET @RQ = '2019-09-01';

;WITH
  tAppDays (fDay) AS
  (
  SELECT @RQ AS fDay
  UNION ALL
  SELECT fDay + 1 FROM tAppDays WHERE DateDiff(Month,fDay+1,@RQ) = 0
  )
SELECT * FROM tAppDays ORDER BY fDAY
下面是运行结果
fDay
---------------------
2019-09-01 00:00:00
2019-09-02 00:00:00
2019-09-03 00:00:00
...
2019-09-23 00:00:00
2019-09-24 00:00:00
2019-09-25 00:00:00
2019-09-26 00:00:00
2019-09-27 00:00:00
2019-09-28 00:00:00
2019-09-29 00:00:00
2019-09-30 00:00:00
三、获得子字符串列表
利用递归来获得给定字符串的SPLIT方法
-- 利用递归来获得给定字符串的SPLIT方法

DECLARE @CommentStr NVARCHAR(4000)='总经理室|销售部|会计部|人事部|工会|后勤部|生产计划部|动力分厂|质量检验部|运输部'
DECLARE @Split   NVARCHAR(1)='|';

WITH Temp AS
(  SELECT 1 AS Num UNION ALL
   SELECT Num + 1
   FROM TEMP WHERE Num<Len(@CommentStr)   )
SELECT
  RN = Row_Number() Over(ORDER BY Num),
  SplitStr = SUBSTRING(@CommentStr,Num,CHARINDEX(@Split,@CommentStr+@Split,Num)-Num)
FROM Temp WHERE SUBSTRING(@Split+@CommentStr,Num,1) = @Split OPTION(MAXRECURSION 0);
下面是运行效果
RN  SplitStr
------------------------
 1  总经理室
 2  销售部
 3  会计部
 4  人事部
 5  工会
 6  后勤部
 7  生产计划部
 8  动力分厂
 9  质量检验部
10  运输部
给定一个带有分隔符的字符串,通过这个语句获得各个字段的列表。
--================================================================================================
--   pAppGetSplit '|','科目名称|身份证号|学员姓名|教练编号|教练姓名|培训次数|合计次数|负责比例'
================================================================================================
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'pAppGetSplit' AND type = 'P')
   DROP PROCEDURE pAppGetSplit
GO
CREATE PROCEDURE pAppGetSplit
  @Split       VARCHAR(1),
  @STR         NVARCHAR(4000)
AS
  ;WITH Temp AS   -- 根据分隔符|获得字段列表
  (  SELECT 1 AS Num UNION ALL
   SELECT Num + 1
   FROM TEMP WHERE Num<Len(@STR)   )
  SELECT
  RN = Row_Number() Over(ORDER BY Num),
  SplitStr = SUBSTRING(@STR,Num,CHARINDEX(@Split,@STR+@Split,Num)-Num)
  FROM Temp WHERE SUBSTRING(@Split+@STR,Num,1) = @Split OPTION(MAXRECURSION 0);
GO
下面是运行效果
+---+---------------------+
|RN |  SplitStr       |
|----+---------------------|
| 1 |  科目名称       |
| 2 |  身份证号       |
| 3 |  学员姓名       |
| 4 |  教练编号       |
| 5 |  教练姓名       |
| 6 |  培训次数       |
| 7 |  合计次数       |
| 8 |  负责比例       |
+---+---------------------+
四、获得本周指定周几的日期
根据指定获得的周几,得到日期
--获得本周周一的日期
DECLARE @Z SMALLINT
-- [1,2,3,4,5,6,7]分别代表[周一,周二,周三,周四,周五,周六,周日]
SET @Z=1
SELECT
  GetDate() 今天,
  DATEPART(Weekday,GetDate()) 今天序号,
  (DATEPART(Weekday,GetDate()) + @@DATEFIRST-1)%7 今天是周几,
  DATEADD(Day,@Z-(DATEPART(Weekday,GetDate()) + @@DATEFIRST-1)%7,GetDate()) 本周周一
到此这篇关于数据库之SQL技巧整理案例的文章就介绍到这了,更多相关SQL技巧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


关注下面的标签,发现更多相似文章