我正在从MySQL迁移到SQL Server。以下是我在MySQL中进行的查询,但不确定如何在SQL Server中使用变量。
SET @listid = 0;
SELECT
list_id, last_updated, price, daily_return,
@cumu_ret := ROUND(
IF (@listid = list_id,
IF(daily_return IS NULL, 1.0, @cumu_ret * (1 + daily_return)),
IF(daily_return IS NULL, 1.0, last_cumulative_return * (1 + daily_return))), 10) AS cumulative_return,
@listid := list_id AS set_id
FROM
daily_return
ORDER BY
list_id, last_updated
SQL Server具有SUM() OVER
函数,但理想情况下我需要PRODUCT() OVER
。
有什么想法我能做什么?
编辑:当我尝试以下查询...
DECLARE @listid int = 0;
DECLARE @cumu_ret decimal(24,10) = NULL;
SELECT
list_id, last_updated, price, daily_return,
@cumu_ret = ROUND(
IIF (@listid = list_id,
IIF(daily_return IS NULL, 1.0, @cumu_ret * (1 + daily_return)),
IIF(daily_return IS NULL, 1.0, last_cumulative_return * (1 + daily_return))), 10),
@listid = list_id
FROM
#daily_return
ORDER BY
list_id, last_updated
它抛出一个错误:
为变量分配值的SELECT语句不得与数据检索操作结合使用。
编辑2:
错误是一种症状,而不是我的主要问题。我无法使用任何建议的解决方法。为变量分配值的SELECT语句不得与数据检索操作组合
我正在尝试使用PRODUCT() OVER
功能。基本上,在该列中,我尝试获取先前的累积返回值,并将新行的值设置为先前的累积*(1 + daily_return)。
答案 0 :(得分:0)
要实施产品汇总,请记住您的代数:
declare @t table (i int)
insert into @t(i) values (1),(2),(3),(4),(5)
select exp(sum(log(i))) product
from @t
输出
product
----------------------
120
我的数据为负数。
然后我们需要添加一些模块化算法:
declare @t table (i int)
insert into @t(i) values (-1),(-2),(3),(-4),(5)
select exp(sum(log(abs(i))))
* case when sum(case when sign(i) = -1 then 1 else 0 end) % 2 = 1 then -1 else 1 end product
from @t
输出
product
----------------------
-120
答案 1 :(得分:0)
您的问题是,在SQL Sever中,您需要在SELECT语句之外设置变量(如使用DECLARE正确完成的操作一样)。
不允许这些行:
@cumu_ret = ROUND(
IIF (@listid = list_id,
IIF(daily_return IS NULL, 1.0, @cumu_ret * (1 + daily_return)),
IIF(daily_return IS NULL, 1.0, last_cumulative_return * (1 + daily_return))), 10),
@listid = list_id
您想要更多类似这样的东西:
DECLARE @listid int = 0;
DECLARE @cumu_ret decimal(24,10) = NULL;
SET @listid = list_id;
SET @cumu_ret = select ROUND(
IIF (@listid = list_id,
IIF(daily_return IS NULL, 1.0, @cumu_ret * (1 + daily_return)),
IIF(daily_return IS NULL, 1.0, last_cumulative_return * (1 + daily_return))), 10) as cumn_ret from #daily_return
SELECT
list_id, last_updated, price, daily_return,
@cumu_ret, @listid
FROM
#daily_return
ORDER BY
list_id, last_updated
这可能需要进行一些修改-我只是想为您指明正确的方向...您可能还想研究对动态变量进行while
循环
答案 2 :(得分:0)
根据David Browne的回答,以下是我目前所拥有的。这是一个很好的起点。在MySQL中,我能够以增量方式保存PRODUCT()OVER输出,而在MS SQL中可能无法这样做,并且可能需要使用游标...让我们看看。
WITH daily_return AS (
SELECT 0 AS ID, 0 AS daily_return UNION ALL
SELECT 1 AS ID, 0.1 AS daily_return UNION ALL
SELECT 2 AS ID, -0.2 AS daily_return UNION ALL
SELECT 3 AS ID, 0 AS daily_return UNION ALL
SELECT 4 AS ID, -1.1 AS daily_return UNION ALL
SELECT 5 AS ID, 0.3 AS daily_return UNION ALL
SELECT 6 AS ID, 0.2 AS daily_return
)
select id, daily_return,
(exp(sum(log(abs(1+daily_return))) over (order by id)))
* (case when (sum(case when sign(1+daily_return) = -1 then 1 else 0 end) over (order by id)) % 2 = 1 then -1 else 1 end) product
from daily_return