我的数据表如下,需要使用t-sql生成
Year | Id | Entitle | Use | Max
-----------------------------------
2016 | 0001 | 15 | 5 | 20
2017 | 0001 | 15 | 2 | 20
2018 | 0001 | 15 | 4 | 20
我需要每年进行开门和关门,今年的开门将是去年(开门+授权-使用),但不能超过Max,如果超过Max,则“ Max”为开门。
这是我期望的结果
year | Id | Opening | Entitle | Use | Max | Closing
-----------------------------------------------------
2016 | 0001 | 0 | 15 | 5 | 20 | 10
2017 | 0001 | 10 | 15 | 2 | 20 | 23
2018 | 0001 | 20 | 15 | 4 | 20 | 31
答案 0 :(得分:1)
这是另一种选择,递归CTE将带您到达那里。
DECLARE @TestData TABLE
(
[Year] INT
, [Id] NVARCHAR(10)
, [Entitle] INT
, [Use] INT
, [Max] INT
);
INSERT INTO @TestData (
[Year]
, [Id]
, [Entitle]
, [Use]
, [Max]
)
VALUES ( 2016, '0001', 15, 5, 20 )
, ( 2017, '0001', 15, 2, 20 )
, ( 2018, '0001', 15, 4, 20 );
INSERT INTO @TestData (
[Year]
, [Id]
, [Entitle]
, [Use]
, [Max]
)
VALUES ( 2015, '0002', 20, 7, 20 )
, ( 2016, '0002', 20, 7, 20 )
, ( 2017, '0002', 20, 4, 20 )
, ( 2018, '0002', 20, 13, 20 );
WITH [cte]
AS ( SELECT [a].[Year]
, [a].[Id]
, 0 AS [Opening]
, [a].[Entitle]
, [a].[Use]
, [a].[Entitle] - [a].[Use] AS [Closing]
FROM @TestData [a]
--Cross apply here to get our first record, earliest year for each Id for our anchor
CROSS APPLY (
SELECT [aa].[Id]
, MIN([aa].[Year]) AS [Year]
FROM @TestData [aa]
WHERE [aa].[Id] = [a].[Id]
GROUP BY [aa].[Id]
) [aaa]
WHERE [a].[Year] = [aaa].[Year]
AND [a].[Id] = [aaa].[Id]
UNION ALL
SELECT [c].[Year]
, [c].[Id]
, CASE WHEN [b].[Closing] > [c].[Max] THEN [c].[Max]
ELSE [b].[Closing]
END
, [c].[Entitle]
, [c].[Use]
, CASE WHEN [b].[Closing] > [c].[Max] THEN [c].[Max]
ELSE [b].[Closing]
END + [c].[Entitle] - [c].[Use] AS [Closing]
FROM [cte] [b]
INNER JOIN @TestData [c]
ON [c].[Id] = [b].[Id]
AND [c].[Year] = [b].[Year] + 1 )
SELECT *
FROM [cte]
ORDER BY [cte].[Id]
, [cte].[Year];
答案 1 :(得分:0)
简单的SQL在这里还不够。您需要遍历每行并根据上一年计算收盘价和开盘价。
这个想法是循环遍历每一行。存储结果。将结果添加到临时表中。
我已经在这里给您编写了代码。请注意,我已经使用SSMS来实现它。
DECLARE @TempTable table (_ID varchar(255),Year int,Opening int, Entitle int,Used int,Max int, Closing int)
DECLARE @idColumn INT
DECLARE @ID varchar(255)
DECLARE @entitle INT
DECLARE @used INT
DECLARE @max INT
DECLARE @opening INT
DECLARE @closing INT
DECLARE @year INT
SELECT @idColumn = min( Id ) FROM MyTable
WHILE @idColumn is not null
BEGIN
SET @year = (SELECT Year FROM MyTable WHERE Id = @idColumn)
SET @ID = (SELECT [_ID] FROM MyTable WHERE Id = @idColumn)
IF @idColumn = 1
BEGIN
SET @entitle = (SELECT Entitle FROM MyTable WHERE Id = @idColumn);
SET @used = (SELECT Used FROM MyTable WHERE Id = @idColumn);
SET @opening = 0;
SET @closing = @opening + @entitle - @used;
SET @max = (SELECT Max FROM MyTable WHERE Id = @idColumn);
END
ELSE
BEGIN
SET @opening = @opening + @entitle - @used;
IF @opening > @max
BEGIN
SET @opening = @max;
END
SET @entitle = (SELECT Entitle FROM MyTable WHERE Id = @idColumn);
SET @used = (SELECT Used FROM MyTable WHERE Id = @idColumn);
SET @max = (SELECT Max FROM MyTable WHERE Id = @idColumn);
SET @closing = @opening + @entitle - @used;
END
INSERT INTO @TempTable (_ID , Year , Opening , Entitle , Used ,Max , Closing )
VALUES (@ID, @year, @opening, @entitle, @used, @max, @closing);
SELECT @idColumn = min( Id ) FROM MyTable WHERE Id > @idColumn
END
SELECT * FROM @TempTable