SQL Server에서 두 날짜 사이의 모든 날짜 가져오기
두 날짜 사이의 모든 날짜를 얻는 방법은 무엇입니까?
변수가 있습니다.@MAXDATE
테이블의 최대 날짜를 저장합니다.이제 나는 모든 날짜를 알고 싶습니다.@Maxdate
그리고.GETDATE()
이 날짜를 커서에 저장하려고 합니다.
지금까지 저는 다음과 같이 했습니다.
;with GetDates As
(
select DATEADD(day,1,@maxDate) as TheDate
UNION ALL
select DATEADD(day,1, TheDate) from GetDates
where TheDate < GETDATE()
)
이는 완벽하게 작동하지만 커서에 이러한 값을 저장하려고 할 때
SET @DateCurSor = CURSOR FOR
SELECT TheDate
FROM GetDates
컴파일 오류
'SET' 키워드 근처의 구문이 잘못되었습니다.
어떻게 해결합니까?
제 첫 번째 제안은 달력 테이블을 사용하는 것입니다. 만약 없다면, 달력 테이블을 만드세요.그것들은 매우 유용합니다.그러면 쿼리는 다음과 같이 간단합니다.
DECLARE @MinDate DATE = '20140101',
@MaxDate DATE = '20140106';
SELECT Date
FROM dbo.Calendar
WHERE Date >= @MinDate
AND Date < @MaxDate;
달력 테이블을 만들고 싶지 않거나 만들 수 없는 경우에도 재귀 CTE 없이 즉시 이 작업을 수행할 수 있습니다.
DECLARE @MinDate DATE = '20140101',
@MaxDate DATE = '20140106';
SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
이에 대한 자세한 내용은 다음을 참조하십시오.
커서에서 이 일련의 날짜를 사용하는 것과 관련하여, 저는 당신이 다른 방법을 찾는 것을 정말로 추천합니다.일반적으로 훨씬 더 나은 성능을 발휘할 수 있는 세트 기반 대안이 있습니다.
데이터를 사용하면 다음과 같습니다.
date | it_cd | qty
24-04-14 | i-1 | 10
26-04-14 | i-1 | 20
28-04-2014에 수량을 얻으려면(당신의 요구 사항으로 알고 있습니다) 위의 내용이 실제로 필요하지 않습니다. 간단히 다음을 사용할 수 있습니다.
SELECT TOP 1 date, it_cd, qty
FROM T
WHERE it_cd = 'i-1'
AND Date <= '20140428'
ORDER BY Date DESC;
특정 항목에 대해 사용하지 않으려면 다음을 수행합니다.
SELECT date, it_cd, qty
FROM ( SELECT date,
it_cd,
qty,
RowNumber = ROW_NUMBER() OVER(PARTITION BY ic_id
ORDER BY date DESC)
FROM T
WHERE Date <= '20140428'
) T
WHERE RowNumber = 1;
이 스크립트를 사용하여 두 날짜 사이의 날짜를 찾을 수 있습니다.이 문서에서 인용한 자료:
DECLARE @StartDateTime DATETIME
DECLARE @EndDateTime DATETIME
SET @StartDateTime = '2015-01-01'
SET @EndDateTime = '2015-01-12';
WITH DateRange(DateData) AS
(
SELECT @StartDateTime as Date
UNION ALL
SELECT DATEADD(d,1,DateData)
FROM DateRange
WHERE DateData < @EndDateTime
)
SELECT DateData
FROM DateRange
OPTION (MAXRECURSION 0)
GO
그냥...이에 대한 보다 간단한 접근 방식은 다음과 같습니다.
declare @sdate date = '2017-06-25'
, @edate date = '2017-07-24';
with dates_CTE (date) as (
select @sdate
Union ALL
select DATEADD(day, 1, date)
from dates_CTE
where date < @edate
)
select *
from dates_CTE;
모든 날짜가 포함된 테이블을 반환하는 테이블 값 함수를 쉽게 만들 수 있습니다.날짜를 문자열로 입력 '01/01/2017' 또는 '01-01-2017' 형식의 날짜를 문자열 형식(103,126...)으로 사용자 지정할 수 있습니다.
사용해 보세요.
CREATE FUNCTION [dbo].[DateRange_To_Table] ( @minDate_Str NVARCHAR(30), @maxDate_Str NVARCHAR(30))
RETURNS @Result TABLE(DateString NVARCHAR(30) NOT NULL, DateNameString NVARCHAR(30) NOT NULL)
AS
begin
DECLARE @minDate DATETIME, @maxDate DATETIME
SET @minDate = CONVERT(Datetime, @minDate_Str,103)
SET @maxDate = CONVERT(Datetime, @maxDate_Str,103)
INSERT INTO @Result(DateString, DateNameString )
SELECT CONVERT(NVARCHAR(10),@minDate,103), CONVERT(NVARCHAR(30),DATENAME(dw,@minDate))
WHILE @maxDate > @minDate
BEGIN
SET @minDate = (SELECT DATEADD(dd,1,@minDate))
INSERT INTO @Result(DateString, DateNameString )
SELECT CONVERT(NVARCHAR(10),@minDate,103), CONVERT(NVARCHAR(30),DATENAME(dw,@minDate))
END
return
end
기능을 실행하려면 다음을 수행합니다.
SELECT * FROM dbo.DateRange_To_Table ('01/01/2017','31/01/2017')
출력은 다음과 같습니다.
01/01/2017 Sunday
02/01/2017 Monday
03/01/2017 Tuesday
04/01/2017 Wednesday
05/01/2017 Thursday
06/01/2017 Friday
07/01/2017 Saturday
08/01/2017 Sunday
09/01/2017 Monday
10/01/2017 Tuesday
11/01/2017 Wednesday
12/01/2017 Thursday
13/01/2017 Friday
14/01/2017 Saturday
15/01/2017 Sunday
16/01/2017 Monday
17/01/2017 Tuesday
18/01/2017 Wednesday
19/01/2017 Thursday
20/01/2017 Friday
21/01/2017 Saturday
22/01/2017 Sunday
23/01/2017 Monday
24/01/2017 Tuesday
25/01/2017 Wednesday
26/01/2017 Thursday
27/01/2017 Friday
28/01/2017 Saturday
29/01/2017 Sunday
30/01/2017 Monday
31/01/2017 Tuesday
이것은 제 상황에서 CTE 테이블을 사용할 수 없기 때문에 약간 까다로운 방법으로 간주될 수 있습니다.sys.all_objects
그런 다음 행 번호를 만들고 시작 날짜를 끝 날짜에 도달할 때까지 추가했습니다.
2018년 7월에 모든 날짜를 생성한 아래 코드를 참조하십시오.하드 코딩된 날짜를 고유 변수로 바꿉니다(SQL Server 2016에서 테스트됨).
select top (datediff(dd, '2018-06-30', '2018-07-31')) ROW_NUMBER()
over(order by a.name) as SiNo,
Dateadd(dd, ROW_NUMBER() over(order by a.name) , '2018-06-30') as Dt from sys.all_objects a
사용해 볼 수 있습니다.
SET LANGUAGE SPANISH
DECLARE @startDate DATE = GETDATE() -- Your start date
DECLARE @endDate DATE = DATEADD(MONTH, 16, GETDATE()) -- Your end date
DECLARE @years INT = YEAR(@endDate) - YEAR(@startDate)
CREATE TABLE #TMP_YEARS (
[year] INT
)
-- Get all posible years between the start and end date
WHILE @years >= 0
BEGIN
INSERT INTO #TMP_YEARS
([year])
SELECT YEAR(@startDate) + @years
SET @years = @years - 1
END
;WITH [days]([day]) AS -- Posible days at a month
(
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL -- days lower than 10
SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL -- days lower than 20
SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26 UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL -- days lower than 30
SELECT 30 UNION ALL SELECT 31 -- days higher 30
),
[months]([month]) AS -- All months at a year
(
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
)
SELECT CONVERT(VARCHAR, a.[year]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, n.[month]))) + CONVERT(VARCHAR, n.[month]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, d.[day]))) + CONVERT(VARCHAR, d.[day]) as [date]
FROM #TMP_YEARS a
CROSS JOIN [months] n -- Join all years with all months
INNER JOIN [days] d on DAY(EOMONTH(CONVERT(VARCHAR, a.[year]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, n.[month]))) + CONVERT(VARCHAR, n.[month]) + '-' + CONVERT(VARCHAR, DAY(EOMONTH(CAST(CONVERT(VARCHAR, a.[year]) + '-' + CONVERT(varchar, n.[month]) + '-15' AS DATE)))))) >= d.[day] AND -- The number of the day can't be higher than the last day of the current month and the current year
CONVERT(VARCHAR, a.[year]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, n.[month]))) + CONVERT(VARCHAR, n.[month]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, d.[day]))) + CONVERT(VARCHAR, d.[day]) <= ISNULL(@endDate, GETDATE()) AND -- The current date can't be higher than the end date
CONVERT(VARCHAR, a.[year]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, n.[month]))) + CONVERT(VARCHAR, n.[month]) + '-' + REPLICATE('0', 2 - LEN(CONVERT(VARCHAR, d.[day]))) + CONVERT(VARCHAR, d.[day]) >= ISNULL(@startDate, GETDATE()) -- The current date should be higher than the start date
ORDER BY a.[year] ASC, n.[month] ASC, d.[day] ASC
출력은 다음과 같습니다. 원하는 대로 날짜 형식을 지정할 수 있습니다.
2019-01-24
2019-01-25
2019-01-26
2019-01-27
2019-01-28
2019-01-29
2019-01-30
2019-01-31
2019-02-01
2019-02-02
2019-02-03
2019-02-04
2019-02-05
2019-02-06
2019-02-07
2019-02-08
2019-02-09
...
create procedure [dbo].[p_display_dates](@startdate datetime,@enddate datetime)
as
begin
declare @mxdate datetime
declare @indate datetime
create table #daterange (dater datetime)
insert into #daterange values (@startdate)
set @mxdate = (select MAX(dater) from #daterange)
while @mxdate < @enddate
begin
set @indate = dateadd(day,1,@mxdate)
insert into #daterange values (@indate)
set @mxdate = (select MAX(dater) from #daterange)
end
select * from #daterange
end
저는 2주 후에 날짜를 기재했습니다.변수 @period OR 함수 diff(dd, @date_start, @date_end)를 사용할 수 있습니다.
declare @period INT, @date_start datetime, @date_end datetime, @i int;
set @period = 14
set @date_start = convert(date,DATEADD(D, -@period, curent_timestamp))
set @date_end = convert(date,current_timestamp)
set @i = 1
create table #datesList(dts datetime)
insert into #datesList values (@date_start)
while @i <= @period
Begin
insert into #datesList values (dateadd(d,@i,@date_start))
set @i = @i + 1
end
select cast(dts as DATE) from #datesList
Drop Table #datesList
이것이 제가 사용할 방법입니다.
DECLARE
@DateFrom DATETIME = GETDATE(),
@DateTo DATETIME = DATEADD(HOUR, -1, GETDATE() + 2); -- Add 2 days and minus one hour
-- Dates spaced a day apart
WITH MyDates (MyDate)
AS (
SELECT @DateFrom
UNION ALL
SELECT DATEADD(DAY, 1, MyDate)
FROM MyDates
WHERE MyDate < @DateTo
)
SELECT
MyDates.MyDate
, CONVERT(DATE, MyDates.MyDate) AS [MyDate in DATE format]
FROM
MyDates;
다음은 유사한 예이지만, 쿼리가 작동하는 방식을 이해하는 데 도움이 되도록 날짜를 한 시간 간격으로 지정합니다.
-- Alternative example with dates spaced an hour apart
WITH MyDates (MyDate)
AS (SELECT @DateFrom
UNION ALL
SELECT DATEADD(HOUR, 1, MyDate)
FROM MyDates
WHERE MyDate < @DateTo
)
SELECT
MyDates.MyDate
FROM
MyDates;
보시다시피 쿼리는 빠르고 정확하며 다양합니다.
SQL Server 재귀 CTE를 사용할 수 있습니다.
DECLARE
@MinDate DATE = '2020-01-01',
@MaxDate DATE = '2020-02-01';
WITH Dates(day) AS
(
SELECT CAST(@MinDate as Date) as day
UNION ALL
SELECT CAST(DATEADD(day, 1, day) as Date) as day
FROM Dates
WHERE CAST(DATEADD(day, 1, day) as Date) < @MaxDate
)
SELECT* FROM dates;
declare @start_dt as date = '1/1/2021'; -- Date from which the calendar table will be created.
declare @end_dt as date = '1/1/2022'; -- Calendar table will be created up to this date (not including).
declare @dates as table (
date_id date primary key,
date_year smallint,
date_month tinyint,
date_day tinyint,
weekday_id tinyint,
weekday_nm varchar(10),
month_nm varchar(10),
day_of_year smallint,
quarter_id tinyint,
first_day_of_month date,
last_day_of_month date,
start_dts datetime,
end_dts datetime
)
while @start_dt < @end_dt
begin
insert into @dates(
date_id, date_year, date_month, date_day,
weekday_id, weekday_nm, month_nm, day_of_year, quarter_id,
first_day_of_month, last_day_of_month,
start_dts, end_dts
)
values(
@start_dt, year(@start_dt), month(@start_dt), day(@start_dt),
datepart(weekday, @start_dt), datename(weekday, @start_dt), datename(month, @start_dt), datepart(dayofyear, @start_dt), datepart(quarter, @start_dt),
dateadd(day,-(day(@start_dt)-1),@start_dt), dateadd(day,-(day(dateadd(month,1,@start_dt))),dateadd(month,1,@start_dt)),
cast(@start_dt as datetime), dateadd(second,-1,cast(dateadd(day, 1, @start_dt) as datetime))
)
set @start_dt = dateadd(day, 1, @start_dt)
end
-- sample of the data
select
top 50 *
--into master.dbo.DimDate
from @dates d
order by date_id
DECLARE @FirstDate DATE = '2018-01-01'
DECLARE @LastDate Date = '2018-12-31'
DECLARE @tbl TABLE(ID INT IDENTITY(1,1) PRIMARY KEY,CurrDate date)
INSERT @tbl VALUES( @FirstDate)
WHILE @FirstDate < @LastDate
BEGIN
SET @FirstDate = DATEADD( day,1, @FirstDate)
INSERT @tbl VALUES( @FirstDate)
END
INSERT @tbl VALUES( @LastDate)
SELECT * FROM @tbl
언급URL : https://stackoverflow.com/questions/23290454/get-all-dates-between-two-dates-in-sql-server
'programing' 카테고리의 다른 글
WP_REST_Request에서 쿼리 매개 변수에 액세스할 수 없는 이유는 무엇입니까? (0) | 2023.07.07 |
---|---|
github에서 "실제" 커밋 날짜/시간 참조(시간/일) (0) | 2023.07.07 |
vuex 가입자의 메서드를 어떻게 감시합니까? (0) | 2023.07.02 |
Firestore 하나의 필드만 업데이트 (0) | 2023.07.02 |
Electron을 사용할 때 Angular 2의 기본 href를 어떻게 구성해야 합니까? (0) | 2023.07.02 |