如何获取两个日期之间的日期?
我有一个变量@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”附近的语法不正确。
如何解决这个问题。
提前致谢
答案 0 :(得分:45)
我的第一个建议是使用您的calendar table,如果您没有,请创建一个。它们非常有用。您的查询就像:
一样简单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
要获得2014年4月28日的数量(我收集的是您的要求),您实际上并不需要上述任何一项,您只需使用:
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;
答案 1 :(得分:19)
您可以使用此脚本查找两个日期之间的日期。 Reference taken from this Article:
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
答案 2 :(得分:1)
轻松创建一个表值函数,该函数将返回包含所有日期的表。 输入日期为字符串 您可以使用字母格式(103,126 ...)中的“01/01/2017”或“01 -01-2017”格式自定义日期
试试这个
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
答案 3 :(得分:1)
您可以尝试以下方法:
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
...
答案 4 :(得分:0)
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
答案 5 :(得分:0)
只是说......这是一个更简单的方法:
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
答案 6 :(得分:0)
我列出了2周后的日期。你可以使用变量@period OR函数datediff(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
答案 7 :(得分:0)
这是我将使用的方法。
import re
input_sen = 'hello! how are you? please remember capitalization. EVERY time.'
sentence = re.split(pass_your_punctuation_list_here, input_sen)
for i in sentence:
print(i.strip().capitalize(), end='')
这是一个类似的例子,但这次日期间隔一小时,以进一步帮助理解查询的工作原理:
from nltk.tokenize import sent_tokenize
input_sen = 'hello! how are you? please remember capitalization. EVERY time.'
sentences = sent_tokenize(input_sen)
sentences = [sent.capitalize() for sent in sentences]
print(sentences)
如您所见,查询快速,准确且通用。
答案 8 :(得分:0)
这被认为是有点棘手的方法,因为在我的情况下,我不能使用CTE表,因此决定与“ sys.all_objects”联接,然后创建行号并将其添加到开始日期,直到达到结束日期。
请参阅下面的代码,其中我在2018年7月生成了所有日期。用您自己的变量替换硬编码的日期(在SQL Server 2016中经过测试):
's/\<DST=123\.12\.12\.[0-9]{1,3}\>/DST=xxx.xxx.xxx.xxx/g'
^^ ^^
答案 9 :(得分:0)
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;
答案 10 :(得分:-1)
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