注:私はあまり論理的には(より良い性能)を読み取り有する第2溶液(非再帰的)を追加しました。
1)あなたはrecursive CTE(デモhere)使用することができます
DECLARE @Test TABLE
(
ID INT IDENTITY NOT NULL UNIQUE, --ID is for insert order
ProductCode VARCHAR(10) NOT NULL,
[Date] SMALLDATETIME NOT NULL,
PRIMARY KEY(ProductCode, [Date])
);
INSERT @Test (ProductCode , [Date])
SELECT 'Foo' , '20120401'
UNION ALL SELECT 'Foo' , '20120402'
UNION ALL SELECT 'Foo' , '20120403'
UNION ALL SELECT 'Foo' , '20120404'
--UNION ALL SELECT 'Foo' , '20120405'
UNION ALL SELECT 'Foo' , '20120406'
UNION ALL SELECT 'Foo' , '20120407'
UNION ALL SELECT 'Foo' , '20120408'
UNION ALL SELECT 'Foo' , '20120409'
UNION ALL SELECT 'Foo' , '20120410'
UNION ALL SELECT 'Foo' , '20120415'
UNION ALL SELECT 'Foo' , '20120416'
UNION ALL SELECT 'Foo' , '20120417';
DECLARE @MyProductCode VARCHAR(10),
@MyDate SMALLDATETIME;
SELECT @MyProductCode = 'Foo',
@MyDate = '20120402';
WITH CteRecursive
AS
(
--Starting row
SELECT t.ID,
t.ProductCode,
t.[Date],
1 AS RowType
FROM @Test t
WHERE t.ProductCode = @MyProductCode
AND t.[Date] = @MyDate
UNION ALL
--Add the next days DATEADD(DAY, +1, ..)
SELECT crt.ID,
crt.ProductCode,
crt.[Date],
2 AS RowType
FROM CteRecursive prev
INNER JOIN @Test crt ON DATEADD(DAY, 1, prev.[Date]) = crt.[Date] AND prev.RowType IN (1,2)
UNION ALL
--Add the previous days DATEADD(DAY, -1, ..)
SELECT crt.ID,
crt.ProductCode,
crt.[Date],
0 AS RowType
FROM CteRecursive prev
INNER JOIN @Test crt ON DATEADD(DAY, -1, prev.[Date]) = crt.[Date] AND prev.RowType IN (0,1)
)
SELECT *
FROM CteRecursive r
ORDER BY r.[Date]
/*--Or
SELECT MIN(r.[Date]) AS BeginDate, MAX(r.[Date]) AS EndDate
FROM CteRecursive r
*/
結果:
ID ProductCode Date RowType
----------- ----------- ----------------------- -------
1 Foo 2012-04-01 00:00:00 0
2 Foo 2012-04-02 00:00:00 1
3 Foo 2012-04-03 00:00:00 2
4 Foo 2012-04-04 00:00:00 2
2)非再帰的なソリューション:
DECLARE @Test TABLE
(
ProductCode VARCHAR(10) NOT NULL,
[Date] SMALLDATETIME NOT NULL,
PRIMARY KEY(ProductCode, [Date])
);
INSERT @Test (ProductCode , [Date])
SELECT 'Foo' , '20120401'
UNION ALL SELECT 'Foo' , '20120402'
UNION ALL SELECT 'Foo' , '20120403'
UNION ALL SELECT 'Foo' , '20120404'
--UNION ALL SELECT 'Foo' , '20120405'
UNION ALL SELECT 'Foo' , '20120406'
UNION ALL SELECT 'Foo' , '20120407'
UNION ALL SELECT 'Foo' , '20120408'
UNION ALL SELECT 'Foo' , '20120409'
UNION ALL SELECT 'Foo' , '20120410'
UNION ALL SELECT 'Foo' , '20120415'
UNION ALL SELECT 'Foo' , '20120416'
UNION ALL SELECT 'Foo' , '20120417';
DECLARE @MyProductCode VARCHAR(10),
@MyDate SMALLDATETIME;
SELECT @MyProductCode = 'Foo',
@MyDate = '20120402';
DECLARE @StartDate SMALLDATETIME,
@EndDate SMALLDATETIME;
SELECT @EndDate = MAX(b.[Date])
FROM
(
SELECT a.[Date],
ROW_NUMBER() OVER(ORDER BY a.Date ASC)-1 AS RowNum
FROM @Test a
WHERE a.ProductCode = @MyProductCode
AND a.[Date] >= @MyDate
) b
WHERE b.[Date] = DATEADD(DAY, b.RowNum, @MyDate);
SELECT @StartDate = MIN(b.[Date])
FROM
(
SELECT a.[Date],
ROW_NUMBER() OVER(ORDER BY a.Date DESC)-1 AS RowNum
FROM @Test a
WHERE a.ProductCode = @MyProductCode
AND a.[Date] <= @MyDate
) b
WHERE b.[Date] = DATEADD(DAY, -b.RowNum, @MyDate);
SELECT @StartDate [@StartDate], @EndDate [@EndDate];
SELECT LEFT(CONVERT(VARCHAR(10), @StartDate, 101),5) [@StartDate], LEFT(CONVERT(VARCHAR(10), @EndDate, 101),5) [@EndDate];
結果:
を
@StartDate @EndDate
----------------------- -----------------------
2012-04-01 00:00:00 2012-04-04 00:00:00
@StartDate @EndDate
---------- --------
04/01 04/04
バージョンは何? –
私はSQL Server 2005を考えています。[sql-server-2005]タグで2つの質問があります。 –