假设我想在SQL中编写表值函数,它返回一个表,每个月的第一天在参数日期之间,最简单的方法是什么?
例如,fnFirstOfMonths('10/31/10', '2/17/11')
将返回带有的单列表11/1/10, 12/1/10, 1/1/11
,并2/1/11
作为元素.
我的第一直觉只是使用while循环并重复插入几个月的前几天,直到我到达开始日期之前.看起来应该有更优雅的方式来做到这一点.
感谢您的任何帮助,您可以提供.
这样的东西可以在不在函数内部的情况下工作:
DECLARE @LowerDate DATE
SET @LowerDate = GETDATE()
DECLARE @UpperLimit DATE
SET @UpperLimit = '20111231'
;WITH Firsts AS
(
SELECT
DATEADD(DAY, -1 * DAY(@LowerDate) + 1, @LowerDate) AS 'FirstOfMonth'
UNION ALL
SELECT
DATEADD(MONTH, 1, f.FirstOfMonth) AS 'FirstOfMonth'
FROM
Firsts f
WHERE
DATEADD(MONTH, 1, f.FirstOfMonth) <= @UpperLimit
)
SELECT *
FROM Firsts
Run Code Online (Sandbox Code Playgroud)
它使用一种称为CTE(公用表表达式)的东西 - 可在SQL Server 2005及更高版本和其他数据库系统中使用.
在这种情况下,我通过确定@LowerDate
指定日期的第一个月开始递归CTE ,然后迭代添加一个月到前一个月的第一个月,直到达到上限.
或者,如果您想将其打包在存储函数中,您也可以这样做:
CREATE FUNCTION dbo.GetFirstOfMonth(@LowerLimit DATE, @UpperLimit DATE)
RETURNS TABLE
AS
RETURN
WITH Firsts AS
(
SELECT
DATEADD(DAY, -1 * DAY(@LowerLimit) + 1, @LowerLimit) AS 'FirstOfMonth'
UNION ALL
SELECT
DATEADD(MONTH, 1, f.FirstOfMonth) AS 'FirstOfMonth'
FROM
Firsts f
WHERE
DATEADD(MONTH, 1, f.FirstOfMonth) <= @UpperLimit
)
SELECT * FROM Firsts
Run Code Online (Sandbox Code Playgroud)
然后像这样调用它:
SELECT * FROM dbo.GetFirstOfMonth('20100522', '20100831')
Run Code Online (Sandbox Code Playgroud)
获得这样的输出:
FirstOfMonth
2010-05-01
2010-06-01
2010-07-01
2010-08-01
Run Code Online (Sandbox Code Playgroud)
PS:通过使用DATE
SQL Server 2008及更新版本中的数据类型 - 我修复了Richard评论的两个"错误".如果您使用的是SQL Server 2005,则必须使用DATETIME
- 并处理您正在获得时间部分的事实.
归档时间: |
|
查看次数: |
8226 次 |
最近记录: |