1 28/11/2011 ...
如何在SQL中编写函数来实现上述模式?
答案 0 :(得分:2)
您可以在SQL Server中执行以下操作:
DECLARE @BaseDate DATE = '20111107';
DECLARE @EndDate DATE = GETDATE(); --Or the "end of dates in the database"
WITH RecursiveCTE AS (
SELECT
1 AS [Counter],
@BaseDate AS [MyDate]
UNION ALL
SELECT
[Counter] + 1,
DATEADD(DAY, 7, MyDate)
FROM
RecursiveCTE
WHERE
MyDate < @EndDate)
SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);
要处理不准确的日期并将其转换为函数,您可以执行此操作:
--Function definition
CREATE FUNCTION SuperDuperDataCalculator (
@BaseDate DATE = '20131016',
@EndDate DATE = '20131020')
RETURNS @Results TABLE (
[Counter] INT,
[Date] DATE)
AS
BEGIN
WITH RecursiveCTE AS (
SELECT
1 AS [Counter],
@BaseDate AS [MyDate]
UNION ALL
SELECT
[Counter] + 1,
CASE WHEN DATEADD(DAY, 7, MyDate) > @EndDate THEN @EndDate ELSE DATEADD(DAY, 7, MyDate) END
FROM
RecursiveCTE
WHERE
MyDate < @EndDate)
INSERT INTO
@Results
SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);
RETURN;
END;
GO
--Usage
SELECT * FROM SuperDuperDataCalculator('20131016', '20131020');
--Results
Counter Date
1 2013-10-16
2 2013-10-20
请注意,我们必须使用多语句表值函数,因为SQL Server中存在一个错误,它不允许您在简单的表值函数中使用OPTION。另一种方法是从函数中删除OPTION(MAXRECURSION 0)并记住每次引用它时都使用它(即一个相当差的替代方法)。
...最后,如果你想只返回最大计数器值,你可以将其重写为标量值函数,即:
--Function definition
CREATE FUNCTION SuperDuperDataCalculator (
@BaseDate DATE = '20131016',
@EndDate DATE = '20131020')
RETURNS INT
AS
BEGIN
DECLARE @Results TABLE (
[Counter] INT,
[Date] DATE);
DECLARE @ReturnValue INT;
WITH RecursiveCTE AS (
SELECT
1 AS [Counter],
@BaseDate AS [MyDate]
UNION ALL
SELECT
[Counter] + 1,
CASE WHEN DATEADD(DAY, 7, MyDate) > @EndDate THEN @EndDate ELSE DATEADD(DAY, 7, MyDate) END
FROM
RecursiveCTE
WHERE
MyDate < @EndDate)
INSERT INTO
@Results
SELECT * FROM RecursiveCTE OPTION (MAXRECURSION 0);
SELECT @ReturnValue = MAX([Counter]) FROM @Results;
RETURN @ReturnValue;
END;
GO
SELECT dbo.SuperDuperDataCalculator('20131016', '20131020');
答案 1 :(得分:0)
试试这个 - 它将获得所有周并在子查询中分配一个rownumber。然后只选择行号= 1的记录,因为该周可能会有更多结果。因此RowNo = 1
SELECT ROW_NUMBER() OVER(ORDER BY RowNo) AS IncrementalWeek,dte
FROM
(
SELECT DISTINCT DATEPART(ww,CONVERT(VARCHAR(20),createdDate,111)) AS [week],
CONVERT(VARCHAR(20),createdDate,111) AS dte,
ROW_NUMBER() OVER(PARTITION BY DATEPART(ww,Convert(VARCHAR(20),createdDate,111)) ORDER BY DATEPART(ww,CONVERT(VARCHAR(20),createdDate,111))) AS RowNo
FROM YourTable
) AS tble
WHERE RowNo = 1
ORDER BY [week]