一尘不染

想要显示来自SQL Server的12个月的名称

sql

我想显示来自SQLServer的12个月的名称。我虽然完成插入月份名称到临时表,然后在该表上触发选择语句。所以我不得不写12插入表以插入12个月的名称。所以我搜索谷歌找到更好的解决方案,我明白了。

这是SQL语句

WITH R(N) AS
(
    SELECT 0
    UNION ALL
    SELECT N+1 
    FROM R
    WHERE N < 12
)

SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-N,GETDATE())),3) AS [month]
FROM R

上面的脚本可以完美地工作,但是我的问题是我只是不了解它是如何工作的。我从不与CTE合作。

告诉我这是什么意思 WITH R(N) AS

并看到这个SQL

SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-N,GETDATE())),3) AS [month] FROM R
when above sql execute how it is getting value for -N ??
because here i have not set anything for -N ??

所以请任何人帮助我了解整个过程。塞克斯

我的第二阶段问题

只是看一看就告诉我

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)

对我来说还不清楚的是,为什么只有第一次执行以下部分

SELECT 0
UNION ALL
SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

从第二次开始,仅此下面的部分执行

SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

每当我们使用Union编写两个sql语句并执行时,它总是从两个sql状态返回数据,但是特别是在这种情况下,是从第二次开始,为什么只执行以下部分

SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

基本上,我不熟悉递归技术的CTE,这就是为什么事情对我来说还不清楚。如果可能,请讨论CTE递归的工作方式。

DECLARE @TotaDays SMALLINT
DECLARE @Month VARCHAR(15)
DECLARE @Year SMALLINT
DECLARE @date DATETIME 
SET @Month = 'January'
SET @Year = 2015
SET @date = '01 ' + @Month + ' ' + CONVERT(VARCHAR(4),@Year)
SET @TotaDays = 0
SELECT @TotaDays = DATEDIFF(DAY, @date, DATEADD(MONTH, 1, @date))

;WITH months(MonthNumber) AS
(
    SELECT 1
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < @TotaDays
)

select * from months;

阅读 219

收藏
2021-03-17

共1个答案

一尘不染

With R(N)是一个公共表表达式。从MDSN:

可以将公用表表达式(CTE)视为在单个SELECT,INSERT,UPDATE,DELETE或CREATE
VIEW语句的执行范围内定义的临时结果集。CTE与派生表相似,因为它不存储为对象,并且仅在查询期间持续存在。与派生表不同,CTE可以自我引用,并且可以在同一查询中多次引用。

R是结果集(或表),您正在生成的名称。和Nmonth数字。

该CTE特别是递归公用表表达式。从MSDN:

公用表表达式(CTE)提供了能够引用自身的显着优势,从而创建了递归CTE。递归CTE是其中重复执行初始CTE以返回数据子集直到获得完整结果集的CTE。

使用CTE时,我的建议是对名称进行描述。因此,对于您的示例,您可以使用以下代码:

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)
select *
from months;

在我的版本中,months是您正在生成的结果集的名称,并且monthnumber是值。这将产生一个0到12之间的月份编号列表(请参阅Demo)。

结果:

| MONTHNUMBER |
---------------
|           0 |
|           1 |
|           2 |
|           3 |
|           4 |
|           5 |
|           6 |
|           7 |
|           8 |
|           9 |
|          10 |
|          11 |
|          12 |

然后SELECT紧随其后的语句使用CTE结果集的值来获取月份名称。

最终查询(请参见Demo):

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)
SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())),3) AS [month]
FROM months;
2021-03-17