Tsql 如何使今年的开盘价比去年的开盘价有条件?
我有如下数据表,需要使用t-sql生成Tsql 如何使今年的开盘价比去年的开盘价有条件?,tsql,Tsql,我有如下数据表,需要使用t-sql生成 Year | Id | Entitle | Use | Max ----------------------------------- 2016 | 0001 | 15 | 5 | 20 2017 | 0001 | 15 | 2 | 20 2018 | 0001 | 15 | 4 | 20 我需要获得每年的开始和结束,今年的开始将是去年(开始+授权-使用),但不能超过最大值,如果超过最大值,则“最大值
Year | Id | Entitle | Use | Max
-----------------------------------
2016 | 0001 | 15 | 5 | 20
2017 | 0001 | 15 | 2 | 20
2018 | 0001 | 15 | 4 | 20
我需要获得每年的开始和结束,今年的开始将是去年(开始+授权-使用),但不能超过最大值,如果超过最大值,则“最大值”将是开始
这是我所期望的结果
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
简单的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
这里还有另一个选项,递归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];
你可以发布一些你试图得到预期结果的代码示例吗?请编辑你的问题。您如何计算您的
结账
?由于您没有上一年的信息,如何计算2016年的期初?问题是,期初取自去年的收盘价,但不能超过最大值,今年的结帐也将包括今年的结帐。我尝试使用这个左外联接选择TY.*从数据TY左外联接数据LY ON TY.ID=LY.ID和TY.year-1=LY.year,但我无法计算如何获得第一个结帐来计算结帐,如果OP的数据在ID
列中的每一行都有值0001
这行吗?提示:选择@authentice=authentice,@used=used。。。来自MyTable,其中Id=@idColumn代码>。我使用的id列是MyTable的标识。我做了一些更改,现在您有了所要求的_ID列(所有值都相同),感谢Alex Leo为我的问题提供了解决方案,但我认为Tim的解决方案更好,更容易集成到我的项目中。@AlexChea嘿,没问题,至少您有多个解决方案可供选择:-)