我需要在SQL中计算 FULL 月的数量,即
我尝试使用DATEDIFF,即
SELECT DATEDIFF(MONTH, '2009-04-16', '2009-05-15')
但不是在两个日期之间给我整整几个月,它给了我月份部分的差异,即
1
任何人都知道如何计算SQL Server中的整月数量?
答案 0 :(得分:47)
原帖有一些错误......所以我重新编写并将其打包为UDF。
CREATE FUNCTION FullMonthsSeparation
(
@DateA DATETIME,
@DateB DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE @Result INT
DECLARE @DateX DATETIME
DECLARE @DateY DATETIME
IF(@DateA < @DateB)
BEGIN
SET @DateX = @DateA
SET @DateY = @DateB
END
ELSE
BEGIN
SET @DateX = @DateB
SET @DateY = @DateA
END
SET @Result = (
SELECT
CASE
WHEN DATEPART(DAY, @DateX) > DATEPART(DAY, @DateY)
THEN DATEDIFF(MONTH, @DateX, @DateY) - 1
ELSE DATEDIFF(MONTH, @DateX, @DateY)
END
)
RETURN @Result
END
GO
SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-05-15') as MonthSep -- =0
SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-05-16') as MonthSep -- =1
SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-06-16') as MonthSep -- =2
答案 1 :(得分:5)
select case when DATEPART(D,End_dATE) >=DATEPART(D,sTAR_dATE)
THEN ( case when DATEPART(M,End_dATE) = DATEPART(M,sTAR_dATE) AND DATEPART(YYYY,End_dATE) = DATEPART(YYYY,sTAR_dATE)
THEN 0 ELSE DATEDIFF(M,sTAR_dATE,End_dATE)END )
ELSE DATEDIFF(M,sTAR_dATE,End_dATE)-1 END
答案 2 :(得分:4)
dateadd函数可用于偏移到月初。如果endDate的日期部分小于startDate,它将被推送到上个月,因此datediff将给出正确的月数。
DATEDIFF(MONTH, DATEADD(DAY,-DAY(startDate)+1,startDate),DATEADD(DAY,-DAY(startDate)+1,endDate))
答案 3 :(得分:3)
仅适用于 ORACLE ,不适用于SQL-Server:
months_between(to_date ('2009/05/15', 'yyyy/mm/dd'),
to_date ('2009/04/16', 'yyyy/mm/dd'))
整整一个月:
round(months_between(to_date ('2009/05/15', 'yyyy/mm/dd'),
to_date ('2009/04/16', 'yyyy/mm/dd')))
可以在Oracle 8i及更高版本中使用。
答案 4 :(得分:2)
你对一个月的定义是什么?从技术上讲,一个月可能是28,29,30或31天,具体取决于月份和闰年。
你似乎在考虑一个月是30天,因为在你的例子中你忽视了5月有31天,所以为什么不做以下呢?
SELECT DATEDIFF(DAY, '2009-04-16', '2009-05-15')/30
, DATEDIFF(DAY, '2009-04-16', '2009-05-16')/30
, DATEDIFF(DAY, '2009-04-16', '2009-06-16')/30
答案 5 :(得分:0)
对上述功能进行一些更改对我有用。
创建函数 [dbo].[FullMonthsSeparation] ( @DateA 日期时间, @DateB 日期时间 ) 退货积分 作为 开始 声明@Result INT
DECLARE @DateX DATETIME
DECLARE @DateY DATETIME
IF(@DateA < @DateB)
BEGIN
SET @DateX = @DateA
SET @DateY = @DateB
END
ELSE
BEGIN
SET @DateX = @DateB
SET @DateY = @DateA
END
SET @Result = (
SELECT
CASE
WHEN DATEPART(DAY, @DateX) > DATEPART(DAY, @DateY)
THEN DATEDIFF(MONTH, @DateX, @DateY) - iif(EOMONTH(@DateY) = @DateY, 0, 1)
ELSE DATEDIFF(MONTH, @DateX, @DateY)
END
)
RETURN @Result
结束
答案 6 :(得分:0)
我知道这是一个老问题,但是只要日期是> = 1753年1月1日,我就会使用:
var express = require('express');
var bodyParser = require('body-parser')
var app = express();
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
app.get('/', (req, res) => {
res.sendFile(__dirname + './index.html')
})
app.post("/name", (req, res) => {
let fullName = req.body.first + ' ' + req.body.last;
res.json({ name: fullName })
});
答案 7 :(得分:0)
CREATE FUNCTION ufFullMonthDif (@dStart DATE, @dEnd DATE)
RETURNS INT
AS
BEGIN
DECLARE @dif INT,
@dEnd2 DATE
SET @dif = DATEDIFF(MONTH, @dStart, @dEnd)
SET @dEnd2 = DATEADD (MONTH, @dif, @dStart)
IF @dEnd2 > @dEnd
SET @dif = @dif - 1
RETURN @dif
END
GO
SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-01')
SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-29')
SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-30')
SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-05-15')
SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-05-16')
SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-06-16')
SELECT dbo.ufFullMonthDif ('2019-01-31', '2019-02-28')
答案 8 :(得分:0)
SELECT dateadd(dd,number,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) AS gun FROM master..spt_values
WHERE type = 'p'
AND year(dateadd(dd,number,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)))=year(DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
答案 9 :(得分:0)
您可以创建此函数来计算两个日期之间的绝对差。 正如我使用DATEDIFF内置系统功能所发现的那样,我们只会在数月,数日和数年内获得差异。例如:假设有两个日期18-Jan-2018和15-Jan-2019。因此,这些日期之间的差值将由DATEDIFF以12个月的月份给出,而实际上是11个月28天。因此,使用下面给出的函数,我们可以找到两个日期之间的绝对差。
public File createPdfFromTxt(String content) throws IOException, DocumentException {
//define the size of the PDF file, version and output file
File outfile = File.createTempFile("mehr", ".pdf");
Document pdfDoc = new Document(PageSize.A4);
PdfWriter.getInstance(pdfDoc, new FileOutputStream(outfile)).setPdfVersion(PdfWriter.PDF_VERSION_1_7);
pdfDoc.open();
//define the font and also the command that is used to generate new paragraph
Font myfont = new Font();
myfont.setStyle(Font.NORMAL);
myfont.setSize(11);
pdfDoc.add(new Paragraph("\n"));
// add paragraphs into newly created PDF file
File contentFile = File.createTempFile("content", ".txt");
FileUtils.writeStringToFile(contentFile, content);
BufferedReader br = new BufferedReader(new FileReader(contentFile));
String strLine;
while ((strLine = br.readLine()) != null) {
Paragraph para = new Paragraph(strLine + "\n", myfont);
para.setAlignment(Element.ALIGN_JUSTIFIED);
pdfDoc.add(para);
}
pdfDoc.close();
br.close();
return outfile;
}
答案 10 :(得分:0)
您需要做的就是如果结束日期尚未超过开始日期中的月份,则减去额外的月份。
order: {number}
答案 11 :(得分:0)
声明@StartDate date ='2019-01-31' 声明@EndDate date ='2019-02-28'
选择
DATEDIFF(MONTH,@StartDate,@EndDate)+
(
案例
当format(@ StartDate,'yyyy-MM')!= format(@ EndDate,'yyyy-MM')AND DATEPART(DAY,@ StartDate)> DATEPART(DAY,@ EndDate)和DATEPART(DAY,@ EndDate)= DATEPART(DAY,EOMONTH(@EndDate))然后为0
当format(@ StartDate,'yyyy-MM')!= format(@ EndDate,'yyyy-MM')AND DATEPART(DAY,@ StartDate)> DATEPART(DAY,@ EndDate)时为-1
其他0
结束
)
为NumberOfMonths
答案 12 :(得分:0)
我意识到这是一篇旧帖子,但我创建了这个有趣的解决方案,我认为使用CASE语句很容易实现。
使用DATEDIFF估算差异,然后测试使用DATEADD之前和之后的月份以查找最佳日期。这假设1月31日至2月28日是1个月(因为它)。
DECLARE @First date = '2015-08-31'
DECLARE @Last date = '2016-02-28'
SELECT
@First as [First],
@Last as [Last],
DateDiff(Month, @First, @Last) as [DateDiff Thinks],
CASE
WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) +1, @First) <= @Last Then DATEDIFF(Month, @First, @Last) +1
WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) , @First) <= @Last Then DATEDIFF(Month, @First, @Last)
WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) -1, @First) <= @Last Then DATEDIFF(Month, @First, @Last) -1
END as [Actual Months Apart]
答案 13 :(得分:0)
select CAST(DATEDIFF(MONTH, StartDate, EndDate) AS float) -
(DATEPART(dd,StartDate) - 1.0) / DATEDIFF(DAY, StartDate, DATEADD(MONTH, 1, StartDate)) +
(DATEPART(dd,EndDate)*1.0 ) / DATEDIFF(DAY, EndDate, DATEADD(MONTH, 1, EndDate))
答案 14 :(得分:0)
此答案遵循T-SQL格式。我将此问题概念化为 datetime 格式中两个日期点之间的线性时间距离之一,将其称为Time1和Time2; Time1应与您正在处理的“旧时间”值(例如出生日期或窗口小部件创建日期或行程开始日期)对齐,并且Time2应与“更新时间”值(例如快照日期)对齐或小工具完成日期或到达旅程检查点的日期)。
DECLARE @Time1 DATETIME
SET @Time1 = '12/14/2015'
DECLARE @Time2 DATETIME
SET @Time2 = '12/15/2016'
该解决方案利用简单的测量,转换和计算不同长度的多个循环的串行交叉点;这里:世纪,十年,年,月,日(感谢玛雅日历的概念!)。快速感谢:感谢Stack Overflow的其他贡献者向我展示了我在这个过程中拼凑的一些组件功能。我在这个论坛上积极评价这些。
首先,构建一个视野,它是世纪,十年,年,月周期交叉的线性集合,按月增量。使用交叉连接笛卡尔函数。 (想象一下,创建布料,我们将在两个'yyyy-mm'点之间切割一段长度以测量距离):
SELECT
Linear_YearMonths = (centuries.century + decades.decade + years.[year] + months.[Month]),
1 AS value
INTO #linear_months
FROM
(SELECT '18' [century] UNION ALL
SELECT '19' UNION ALL
SELECT '20') centuries
CROSS JOIN
(SELECT '0' [decade] UNION ALL
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') decades
CROSS JOIN
(SELECT '1' [year] 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 '0') years
CROSS JOIN
(SELECT '-01' [month] UNION ALL
SELECT '-02' UNION ALL
SELECT '-03' UNION ALL
SELECT '-04' UNION ALL
SELECT '-05' UNION ALL
SELECT '-06' UNION ALL
SELECT '-07' UNION ALL
SELECT '-08' UNION ALL
SELECT '-09' UNION ALL
SELECT '-10' UNION ALL
SELECT '-11' UNION ALL
SELECT '-12') [months]
ORDER BY 1
然后,将Time1和Time2日期点转换为'yyyy-mm'格式(将它们视为整个布料上的坐标切割点)。保留点的原始日期时间版本:
SELECT
Time1 = @Time1,
[YYYY-MM of Time1] = CASE
WHEN LEFT(MONTH(@Time1),1) <> '1' OR MONTH(@Time1) = '1'
THEN (CAST(YEAR(@Time1) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time1) AS VARCHAR))
ELSE (CAST(YEAR(@Time1) AS VARCHAR) + '-' + CAST(MONTH(@Time1) AS VARCHAR))
END,
Time2 = @Time2,
[YYYY-MM of Time2] = CASE
WHEN LEFT(MONTH(@Time2),1) <> '1' OR MONTH(@Time2) = '1'
THEN (CAST(YEAR(@Time2) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time2) AS VARCHAR))
ELSE (CAST(YEAR(@Time2) AS VARCHAR) + '-' + CAST(MONTH(@Time2) AS VARCHAR))
END
INTO #datepoints
然后,选择'yyyy-mm'单位的序数距离,少一个转换为基数距离(即在确定的切割点从整块布上切下一块布并得到其原始测量值):
SELECT
d.*,
Months_Between = (SELECT (SUM(l.value) - 1) FROM #linear_months l
WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
FROM #datepoints d
Raw Output: 我称之为“原始距离”,因为'yyyy-mm'基数距离的月份成分可能太多了;需要比较一个月内的日期周期组件,以查看上个月的值是否应该计算。具体而言,在该示例中,原始输出距离是“12”。但是12/14的这个错误是在12月15日之前,所以因此只有11个月的时间已经过去了 - 只有一天因为第12个月的失败而感到羞涩。因此,我们必须引入月内的一天周期才能得出最终答案。在\ n之间插入'月,日'位置比较,以确定最新日期点月份是否在名义上计算:
SELECT
d.*,
Months_Between = (SELECT (SUM(l.value) - 1) FROM AZ_VBP.[MY].[edg_Linear_YearMonths] l
WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
+ (CASE WHEN DAY(Time1) < DAY(Time2)
THEN -1
ELSE 0
END)
FROM #datepoints d
Final Output: '11'的正确答案现在是我们的输出。所以,我希望这会有所帮助。谢谢!
答案 15 :(得分:0)
仅在@result部分创建函数不是必需的。例如:
Select Name,
(SELECT CASE WHEN
DATEPART(DAY, '2016-08-28') > DATEPART(DAY, '2016-09-29')
THEN DATEDIFF(MONTH, '2016-08-28', '2016-09-29') - 1
ELSE DATEDIFF(MONTH, '2016-08-28', '2016-09-29') END) as NumberOfMonths
FROM
tableExample;
答案 16 :(得分:0)
WITH
-- Count how many months must be added to @StartDate to exceed @DueDate
MONTHS_SINCE(n, [Month_hence], [IsFull], [RemainingDays] ) AS (
SELECT
1 as n,
DATEADD(Day, -1, DATEADD(Month, 1, @StartDate)) AS Month_hence
,CASE WHEN (DATEADD(Day, -1, DATEADD(Month, 1, @StartDate)) <= @LastDueDate)
THEN 1
ELSE 0
END AS [IsFull]
,DATEDIFF(day, @StartDate, @LastDueDate) as [RemainingDays]
UNION ALL
SELECT
n+1,
--DateAdd(Month, 1, Month_hence) as Month_hence -- No, causes propagation of short month discounted days
DATEADD(Day, -1, DATEADD(Month, n+1, @StartDate)) as Month_hence
,CASE WHEN (DATEADD(Day, -1, DATEADD(Month, n+1, @StartDate)) <= @LastDueDate)
THEN 1
ELSE 0
END AS [IsFull]
,DATEDIFF(day, DATEADD(Day, -1, DATEADD(Month, n, @StartDate)), @LastDueDate)
FROM MONTHS_SINCE
WHERE Month_hence<( @LastDueDate --WHERE Period= 1
)
), --SELECT * FROM MONTHS_SINCE
MONTH_TALLY (full_months_over_all_terms, months_over_all_terms, days_in_incomplete_month ) AS (
SELECT
COALESCE((SELECT MAX(n) FROM MONTHS_SINCE WHERE isFull = 1),1) as full_months_over_all_terms,
(SELECT MAX(n) FROM MONTHS_SINCE ) as months_over_all_terms,
COALESCE((SELECT [RemainingDays] FROM MONTHS_SINCE WHERE isFull = 0),0) as days_in_incomplete_month
) SELECT * FROM MONTH_TALLY;
答案 17 :(得分:0)
SELECT 12 * (YEAR(end_date) - YEAR(start_date)) +
((MONTH(end_date) - MONTH(start_date))) +
SIGN(DAY(end_date) / DAY(start_date));
这适用于SQL SERVER 2000。
答案 18 :(得分:0)
尝试:
trunc(Months_Between(date2, date1))
答案 19 :(得分:-1)
DATEDIFF()用于返回指定范围的两个日期之间的数字边界。为了让它做你想做的事情,你需要做一个额外的调整,以考虑日期越过边界但没有完成整个跨度。
答案 20 :(得分:-2)
尝试这样做:
Declare @Start DateTime
Declare @End DateTime
Set @Start = '11/1/07'
Set @End = '2/29/08'
Select DateDiff(Month, @Start, @End + 1)