[SQL] 날짜 범위 사이의 날짜를 생성
SQL날짜 범위 사이의 날짜를 생성
나는이 주어진 날짜 사이의 날짜 범위를 저장하는 테이블을 채울 필요가 : 09/01/11를 - 10/10/11
따라서이 경우에는 테이블이 09/01/11에서 시작하고 10/10/11에 도착까지 하루를 저장하는 것 나는 현재 SQL 서버를 2008 년 감사를 사용하고 있습니다 - SQL 서버에서이 일을 매끄러운 방법이 있다면 궁금 해서요
해결법
-
==============================
1.SQL 2005 + 간편한; 당신은 숫자 또는 집계 테이블이있는 경우 쉽게. 나는 그것을 아래 위조 :
SQL 2005 + 간편한; 당신은 숫자 또는 집계 테이블이있는 경우 쉽게. 나는 그것을 아래 위조 :
DECLARE @StartDate DATE = '20110901' , @EndDate DATE = '20111001' SELECT DATEADD(DAY, nbr - 1, @StartDate) FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr FROM sys.columns c ) nbrs WHERE nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
당신이 집계 테이블이있는 경우, 테이블과 하위 쿼리를 교체합니다. 아니 재귀 없습니다.
-
==============================
2.당신은 SQL 서버 2005 이상을 사용하는 경우이 시도 :
당신은 SQL 서버 2005 이상을 사용하는 경우이 시도 :
WITH Dates AS ( SELECT [Date] = CONVERT(DATETIME,'09/01/2011') UNION ALL SELECT [Date] = DATEADD(DAY, 1, [Date]) FROM Dates WHERE Date < '10/10/2011' ) SELECT [Date] FROM Dates OPTION (MAXRECURSION 45)
멋진 물건의 좋은 예 당신은 CTE로 할 수 있습니다.
-
==============================
3.- 선언
- 선언
DECLARE @dates TABLE(dt datetime) DECLARE @dateFrom datetime DECLARE @dateTo datetime SET @dateFrom = '2001/01/01' SET @dateTo = '2001/01/12'
- 검색어 :
WHILE(@dateFrom < @dateTo) BEGIN SELECT @dateFrom = DATEADD(day, 1,@dateFrom) INSERT INTO @dates SELECT @dateFrom END
- 출력
SELECT * FROM @dates
-
==============================
4.여기에 재귀를 필요로하지 않는 솔루션과 동시에,이 테이블 반환 함수는 다시 보일러 변수의 선언을 반복 할 필요없이 많은 쿼리에 다시 사용할 수 있습니다. 이것은 재귀를 원하지 않는 사람들을위한 유일한 대안이다.
여기에 재귀를 필요로하지 않는 솔루션과 동시에,이 테이블 반환 함수는 다시 보일러 변수의 선언을 반복 할 필요없이 많은 쿼리에 다시 사용할 수 있습니다. 이것은 재귀를 원하지 않는 사람들을위한 유일한 대안이다.
이 간단한 함수를 만듭니다 :
CREATE FUNCTION [dbo].[GenerateDateRange] (@StartDate AS DATE, @EndDate AS DATE, @Interval AS INT ) RETURNS @Dates TABLE(DateValue DATE) AS BEGIN DECLARE @CUR_DATE DATE SET @CUR_DATE = @StartDate WHILE @CUR_DATE <= @EndDate BEGIN INSERT INTO @Dates VALUES(@CUR_DATE) SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE) END RETURN; END;
그리고에 의해 선택 :
select * from dbo.GenerateDateRange('2017-01-03', '2017-12-01', 1)
-
==============================
5.사용 MVJ의 F_TABLE_DATE 기능, 그것은 순전히 굉장합니다 :
사용 MVJ의 F_TABLE_DATE 기능, 그것은 순전히 굉장합니다 :
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519
이 구현되면 바로 시작 날짜와 종료 날짜를 전달하면 사이의 모든 날짜를 삽입 할 수 있습니다.
-
==============================
6.타인의 편의를 위해 @Abe Miesler의 답변을 사용하여 난 이후 SQL 서버 2008에 대한 TVF로를 건설했다. 그것은 다른 사람들을 도울 수 있습니다 - 나는 TVF 내부의 CTE를 포함 할 수있는 방법을 찾아야했다!
타인의 편의를 위해 @Abe Miesler의 답변을 사용하여 난 이후 SQL 서버 2008에 대한 TVF로를 건설했다. 그것은 다른 사람들을 도울 수 있습니다 - 나는 TVF 내부의 CTE를 포함 할 수있는 방법을 찾아야했다!
--Generate a range of dates with interval option, courtesy of Abe Miessler for the core query here! ALTER FUNCTION [dbo].[DateRange] (@startDate AS DATE, @EndDate AS DATE, @interval AS INT ) RETURNS @Dates TABLE(dateValue DATE) AS BEGIN WITH Dates AS ( SELECT [Date] = CONVERT( DATETIME, @startDate) UNION ALL SELECT [Date] = DATEADD(DAY, ISNULL(@interval, 1), [Date]) FROM Dates WHERE Date < @EndDate) INSERT INTO @Dates SELECT [Date] FROM Dates OPTION(MAXRECURSION 900); RETURN; END;
-
==============================
7.
Declare @StartDate datetime = '2015-01-01' Declare @EndDate datetime = '2016-12-01' declare @DaysInMonth int declare @tempDateRange Table ( DateFrom datetime, DateThru datetime ); While @StartDate<=@EndDate begin SET @DaysInMonth=DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@StartDate),0))) IF DAY(@StartDate)=1 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31 SET @EndDate=DATEADD(DAY,15,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28 SET @EndDate=DATEADD(DAY,12,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29 SET @EndDate=DATEADD(DAY,13,@StartDate) INSERT INTO @tempDateRange (DateFrom,DateThru) VALUES ( @StartDate, @EndDate ) SET @StartDate=DATEADD(DAY,1,@EndDate) IF @EndDate< '2016-12-31' IF DAY(@StartDate)=1 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31 SET @EndDate=DATEADD(DAY,15,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28 SET @EndDate=DATEADD(DAY,12,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29 SET @EndDate=DATEADD(DAY,13,@StartDate) end ; select * from @tempDateRange +++++++++++++++++++++++++++++ Result: DateFrom |DateThru
-
==============================
8.어떤 이유로 당신이 그런 미인에 파생 테이블을 사용할 때와 같은 변수를 선언 할 수없는 경우는 다음과 같이 갈 수 있습니다 :
어떤 이유로 당신이 그런 미인에 파생 테이블을 사용할 때와 같은 변수를 선언 할 수없는 경우는 다음과 같이 갈 수 있습니다 :
select dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d from ( select row_number() over (order by c.object_id) as nbr from sys.columns c ) nbrs where nbr - 1 <= datediff( day, convert(date, '2017-01-01'), convert(date, '2018-12-31') )
그런데,이 날짜 시리즈보기 LookML처럼 보일 수있는 방법입니다 :
view: date_series { derived_table: { sql: select dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d from ( select row_number() over (order by c.object_id) as nbr from sys.columns c ) nbrs where nbr - 1 <= datediff(day, convert(date, '2017-01-01'), convert(date, '2018-12-31')) ;; } dimension: date { primary_key: yes type: date sql: ${TABLE}.d ;; } }
-
==============================
9.
CREATE table #ProductSales (ProjectID Int, ProjectName varchar(100), TotalBillableFees Money, StartDate Date, EndDate Date, DataDate Date) Insert into #ProductSales Values (373104,'Product Sales - Flex Creation Test',40000.00,'2019-04-01','2020-06-01','2019-08-01'), (375111,'Product Sales - SMART',40000.00,'2019-04-01','2019-09-01','2019-08-01') ;WITH Dates AS ( SELECT ProjectiD ,Convert(decimal(10,2),TotalBillableFees/IIF(DATEDIFF(MONTH,StartDate,EndDate)=0,1,DATEDIFF(MONTH,StartDate,EndDate))) AS BillableFeesPerMonths,EndDate ,[Date] = CONVERT(DATETIME,EOMONTH(StartDate)) FROM #ProductSales UNION ALL SELECT ProjectiD,BillableFeesPerMonths,EndDate, [Date] = DATEADD(MONTH, 1, [Date]) FROM Dates WHERE Date < EOMONTH(EndDate) ) SELECT ProjectID,BillableFeesPerMonths, CAST([Date] as Date) Date FROM Dates OPTION (MAXRECURSION 45)
-
==============================
10.나는이 오래된 스레드 실현,하지만 난 여기에 주어진 순환 및 루핑 솔루션의 과잉에 나의 실망을 인정해야한다. 나는 재귀 아무 이상이 매우 비싼 루프보다 없다는 것을 깨닫게 얼마나 많은 사람들 궁금해? 나는 테이블 반환 함수를 만들 수있는 욕망을 이해하지만, 나는 그것이 반복, 재귀없이, 설정을 기반으로, 또는 단일 삽입 문을 반복으로 다음과 같은 훨씬 더 효율적입니다 제안 :
나는이 오래된 스레드 실현,하지만 난 여기에 주어진 순환 및 루핑 솔루션의 과잉에 나의 실망을 인정해야한다. 나는 재귀 아무 이상이 매우 비싼 루프보다 없다는 것을 깨닫게 얼마나 많은 사람들 궁금해? 나는 테이블 반환 함수를 만들 수있는 욕망을 이해하지만, 나는 그것이 반복, 재귀없이, 설정을 기반으로, 또는 단일 삽입 문을 반복으로 다음과 같은 훨씬 더 효율적입니다 제안 :
CREATE FUNCTION dbo.GenerateDateRange(@StartDate AS DATE, @EndDate AS DATE) RETURNS TABLE WITH SCHEMABINDING AS WITH e1(n) AS (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS x(n)) -- 16 records ,e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b) -- 16^2 or 256 records (16*16) ,cteTally(n) AS (SELECT ROW_NUMBER() over (ORDER BY 1) AS n FROM e2 a CROSS JOIN e2 b) -- 16^4 or 65,536 records (256*256) SELECT DATEADD(DAY, n-1, @StartDate) FROM cteTally WHERE n <= DATEDIFF(DAY, @StartDate, @EndDate) + 1; GO
from https://stackoverflow.com/questions/7824831/generate-dates-between-date-ranges by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] SQL 쿼리 - UNION에서 주문을 사용하여 (0) | 2020.03.25 |
---|---|
[SQL] SQL Server에서 실제 일대일 관계를 만드는 방법 (0) | 2020.03.25 |
[SQL] 차이를하는 SQL JOIN (0) | 2020.03.25 |
[SQL] 내부의 'OR'는 조건이 나쁜 생각 JOIN 데? (0) | 2020.03.25 |
[SQL] MySQL은 두 날짜 사이의 차이 (0) | 2020.03.25 |