是否可以在month names
SQl
即
2011-05-01
2011-08-01
是输入
我只想输出
------------
Month
------------
May
June
July
August
如果有任何机构知道该查询,请分享。
答案 0 :(得分:37)
DECLARE @StartDate DATETIME,
@EndDate DATETIME;
SELECT @StartDate = '20110501'
,@EndDate = '20110801';
SELECT DATENAME(MONTH, DATEADD(MONTH, x.number, @StartDate)) AS MonthName
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, @StartDate, @EndDate);
结果:
MonthName
------------------------------
May
June
July
August
(4 row(s) affected)
答案 1 :(得分:29)
您可以使用递归CTE,通过构建日期表并从每个日期获取月份名称来执行此操作:
declare @start DATE = '2011-05-01'
declare @end DATE = '2011-08-01'
;with months (date)
AS
(
SELECT @start
UNION ALL
SELECT DATEADD(month,1,date)
from months
where DATEADD(month,1,date)<=@end
)
select Datename(month,date) from months
答案 2 :(得分:8)
我已修改Jamiec's answer以输出该月的最后一天。
declare @start DATE = '2014-05-01'
declare @end DATE = getdate()
;with months (date)
AS
(
SELECT @start
UNION ALL
SELECT DATEADD(month,1,date)
from months
where DATEADD(month,1,date) < @end
)
select [MonthName] = DATENAME(mm ,Date)
,[MonthNumber] = DATEPART(mm ,Date)
,[LastDayOfMonth] = DATEPART(dd,EOMONTH(Date))
,[MonthYear] = DATEPART(yy ,Date)
from months
提供输出:
MonthName MonthNumber LastDayOfMonth MonthYear
May 5 31 2014
June 6 30 2014
July 7 31 2014
August 8 31 2014
September 9 30 2014
答案 3 :(得分:2)
受到Jamiec's answer的启发,但从day
更大到day
来解决问题:
declare @start DATE
declare @end DATE
SELECT @start='2011-05-19' , @end='2011-08-15'
;with months (date)
AS
(
SELECT DATEADD(DAY,1,EOMONTH(@start,-1))
UNION ALL
SELECT DATEADD(month,1,date)
from months
where DATEADD(month,1,date) < EOMONTH(@end)
)
select Datename(month,date)
from months
答案 4 :(得分:1)
declare @start DATE = '2011-05-30'
declare @end DATE = '2011-06-10'
;with months (date)
AS
(
SELECT @start
UNION ALL
SELECT DATEADD(month,1,date)
from months
where DATEADD(month,1,date)<= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@end)+1,0))
)
select Datename(month,date) from months
答案 5 :(得分:0)
那么,
@bogdhan sahlean给出了一个很好的基于集合的解决方案,但考虑到年份范围为date
到datetime2
的数据类型0001-01-01
和9999-12-31
,将值限制为2048,来自MSDN
日期范围0001-01-01至9999-12-31
CE 1月1,1日至9999年12月31日
即使这是极端的情况,但值得了解。因为有一天有人试图投射170多年的时间:)
即使是最热烈的答案也没有满足一些优势 (当开始日期&gt;结束日期不会显示结束日期的月份时, 此外,默认情况下,100次执行后递归查询失败)。 并且还使用递归cte进行迭代,这在大量使用时是性能的。
现在,更好的解决方案(恕我直言)是使用日历表或计数表来生成两个日期之间的月份。如果无法创建表格,则可以使用更好的替代方法 Itzik ben Gans级联CTE生成数字表。(here) 哪个更快,没有逻辑,物理读取,没有工作台NADA
这是代码
DECLARE @start DATETIME2 = '00010101'
DECLARE @end DATETIME2 = '99991231'
;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
,lv4 AS (SELECT 0 g FROM lv3 a CROSS JOIN lv3 b) -- 65,536
,lv5 AS (SELECT 0 g FROM lv4 a CROSS JOIN lv4 b) -- 4,294,967,296
,Tally (n) AS (SELECT 0 UNION SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv5)
SELECT DATENAME(YEAR,DATEADD(MONTH,N,@start)) AS [Year Part], DATENAME(MONTH,DATEADD(MONTH,n,@start)) AS [Month Part]
FROM Tally where N between 0 and DATEDIFF(mm,@start,@end)
ORDER BY n;
注意:我已添加SELECT 0
以从第0位开始数字
我的电脑中显示的性能是
Itzik方法
(119988行(s)受影响)
SQL Server执行时间:CPU时间= 187毫秒,已用时间= 706 女士。 SQL Server解析和编译时间:CPU时间= 0毫秒,已用时间= 0毫秒。
这里给出的一个递归解决方案需要一段时间
(119988行受影响)表&#39;工作台&#39;。扫描计数2,合乎逻辑 读取719923,物理读取0,预读取读取0,lob逻辑读取 0,lob物理读取0,lob预读读取0。
SQL Server执行时间:CPU时间= 890毫秒,已用时间= 1069毫秒。
理货表,日历表和itzik数字表之间的性能可能略有不同,但与您提供的所有日期范围的魅力相似。
答案 6 :(得分:0)
创建如下所示的数据库功能
CREATE FUNCTION [dbo].[DateRange]
(@Identifier CHAR(1),@StartDate DATETIME,@EndDate DATETIME)
RETURNS @SelectedRange TABLE(Dates DATE) AS
BEGIN
;WITH cteRange (DateRange) AS (
SELECT @StartDate
UNION ALL
SELECT
CASE
WHEN Upper(@Identifier) = 'H' THEN DATEADD(hh, 1, DateRange)
WHEN Upper(@Identifier) = 'D' THEN DATEADD(dd, 1, DateRange)
WHEN Upper(@Identifier) = 'W' THEN DATEADD(ww, 1, DateRange)
WHEN Upper(@Identifier) = 'M' THEN DATEADD(mm, 1, DateRange)
WHEN Upper(@Identifier) = 'Y' THEN DATEADD(yy, 1, DateRange)
END
FROM cteRange
WHERE DateRange <=
CASE
WHEN Upper(@Identifier) = 'H' THEN DATEADD(hh, -1, @EndDate)
WHEN Upper(@Identifier) = 'D' THEN DATEADD(dd, -1, @EndDate)
WHEN Upper(@Identifier) = 'W' THEN DATEADD(ww, -1, @EndDate)
WHEN Upper(@Identifier) = 'M' THEN DATEADD(mm, -1, @EndDate)
WHEN Upper(@Identifier) = 'Y' THEN DATEADD(yy, -1, @EndDate)
END)
INSERT INTO @SelectedRange (Dates) SELECT DateRange FROM cteRange
OPTION (MAXRECURSION 3660);
RETURN
END
然后使用该函数,我们可以生成日期范围
SELECT * from dbo.DateRange('M','1953-01-01','2019-01-01')
如果要格式化输出,可以将结果存储在表变量中,如下例所示,
DECLARE @tblDateRange TABLE (AutoID INT IDENTITY(1,1),DateRange DATE)
INSERT INTO @tblDateRange SELECT * from dbo.DateRange('M','1953-01-01','2019-01-01')
SELECT
LEFT(DATENAME(MONTH,DateRange),3) [MonthYearValue],YEAR(DateRange) AS [Year]
FROM @tblDateRange
根据我们的需要,我们可以更改
OPTION (MAXRECURSION 3660)
答案 7 :(得分:-1)
如果您的MonthNames
表包含每个月的名称,则可以运行
SELECT MonthName FROM MonthNames WHERE MonthNumber BETWEEN Month(&date1) AND Month(&date2);
表MonthNames就像
MonthName,MonthNumber
1月1日
2月2日
3月3日
依旧......
答案 8 :(得分:-1)
试试这个:
declare
@sd date=getdate(),
@ld date='2016-01-01'
select
Datename(month,dateadd(month,number,GETDATE())),
number
from master.dbo.spt_values
where type='p'
and dateadd(month,number,GETDATE()) <= @ld