[SQL] 두 날짜 사이의 개월
SQL두 날짜 사이의 개월
SQL에서 두 날짜 사이의 월 이름을 얻을 수 있습니다
즉, 2011-05-01과 2011-08-01는 입력입니다 난 그냥 출력으로 원하는
------------
Month
------------
May
June
July
August
어떤 몸이 알고있는 경우가 주를 기쁘게 쿼리합니다.
해결법
-
==============================
1.
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)
-
==============================
2.당신은 날짜의 테이블을 구축하고, 각에서 월 이름을 얻어서, 재귀 CTE하여이 작업을 수행 할 수 있습니다 :
당신은 날짜의 테이블을 구축하고, 각에서 월 이름을 얻어서, 재귀 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
-
==============================
3.나는 출력 Jamiec의 대답뿐만 아니라 달의 마지막 날을 수정했습니다.
나는 출력 Jamiec의 대답뿐만 아니라 달의 마지막 날을 수정했습니다.
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
-
==============================
4.Jamiec의 대답에 의해 영감을, 그러나 더 큰 일에서 하루와 함께 문제를 해결 :
Jamiec의 대답에 의해 영감을, 그러나 더 큰 일에서 하루와 함께 문제를 해결 :
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
-
==============================
5.
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
-
==============================
6.잘, @bogdhan sahlean이 좋은 세트 기반 솔루션을 부여하지만 MSDN에서 연도 범위에 9999-12-31 0001-01-01 자료형 일시 DATETIME2을 고려하여 2,048 개까지의 값을 제한했다
잘, @bogdhan sahlean이 좋은 세트 기반 솔루션을 부여하지만 MSDN에서 연도 범위에 9999-12-31 0001-01-01 자료형 일시 DATETIME2을 고려하여 2,048 개까지의 값을 제한했다
이 극단적 인 사례지만 가치가 알고있는 경우에도. 어느 날 누군가가 170 년 이상 개월 이상 프로젝트하려고하면 무엇부터 :)
심지어 가장 upvoted 답변은 어떤 가장자리 케이스를 이행하지 않는 일을 시작할 때 (> 종료 날짜, 종료 날짜의 월을 표시하지 않습니다 또한 재귀 쿼리는 기본적으로 100 개 실행) 후 실패합니다. 또한 다량으로 사용하는 경우 성능 돼지입니다 반복에 대한 재귀 CTE를 사용.
이제, 더 나은 솔루션 (IMHO)는 두 날짜 사이의 개월을 생성하기 위해 일정 테이블이나 집계 테이블을 사용하는 것입니다. 하나의 테이블을 작성할 수없는 경우, 사용에 더 나은 대안이있다 번호 테이블을 생성하기위한 CTE 계단식 Itzik 벤 간스. (여기) 어느 것이 더 빨리, 더 논리적, 물리적 읽기, 아니 작업 테이블 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;
NB : 나는 0 일 위치에서 숫자를 시작하는 SELECT 0 추가
내 PC에 표시된 성능은
Itzik 방법
의 시간이 소요 여기에 주어진 재귀 솔루션 중 하나
집계 테이블, 달력 테이블과 itzik 번호 테이블 사이의 성능은 약간 다를 수 있지만, 사용자가 제공하는 모든 날짜 범위와 매력처럼 작동 할 수 있습니다.
-
==============================
7.다음과 같은 데이터베이스 함수를 만듭니다
다음과 같은 데이터베이스 함수를 만듭니다
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)
-
==============================
8.이 시도:
이 시도:
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
from https://stackoverflow.com/questions/7885851/months-between-two-dates by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] PostgreSQL을의 범위에서 날짜 목록을 얻기 (0) | 2020.04.25 |
---|---|
[SQL] SQL은 월 및 연도에 의해 그룹화 (0) | 2020.04.25 |
[SQL] 테이블의 한 열을 기준으로 중복 된 값을 제거 (0) | 2020.04.25 |
[SQL] SQL 수 (*) 성능 (0) | 2020.04.25 |
[SQL] 단일 쿼리에서 여러 개의 CTE (0) | 2020.04.25 |