我尝试执行以下计算
示例数据:
CREATE TABLE #Table1
(
rno int identity(1,1),
ccp varchar(50),
[col1] INT,
[col2] INT,
[col3] INT,
col4 as [col2]/100.0
);
INSERT INTO #Table1
(ccp,[col1],[col2],[col3])
VALUES ('ccp1',15,10,1100),
('ccp1',20,10,1210),
('ccp1',30,10,1331),
('ccp2',10,15,900),
('ccp2',15,15,1000),
('ccp2',20,15,1010)
+-----+------+------+------+------+----------+
| rno | ccp | col1 | col2 | col3 | col4 |
+-----+------+------+------+------+----------+
| 1 | ccp1 | 15 | 10 | 1100 | 0.100000 |
| 2 | ccp1 | 20 | 10 | 1210 | 0.100000 |
| 3 | ccp1 | 30 | 10 | 1331 | 0.100000 |
| 4 | ccp2 | 10 | 15 | 900 | 0.150000 |
| 5 | ccp2 | 15 | 15 | 1000 | 0.150000 |
| 6 | ccp2 | 20 | 15 | 1010 | 0.150000 |
+-----+------+------+------+------+----------+
注意:每个ccp不仅可以3
条记录N
no.of记录
预期结果:
1083.500000 --1100 - (15 * (1+0.100000))
1169.850000 --1210 - ((20 * (1+0.100000)) + (15 * (1+0.100000)* (1+0.100000)) )
1253.835000 --1331 - ((30 * (1+0.100000)) + (20 * (1+0.100000)* (1+0.100000)) + (15 * (1+0.100000)* (1+0.100000) *(1+0.100000)) )
888.500000 --900 - (10 * (1+0.150000))
969.525000 --1000 - ((15 * (1+0.150000)) + (10 * (1+0.150000)* (1+0.150000)) )
951.953750 --1010 - ((20 * (1+0.150000)) + (15 * (1+0.150000)* (1+0.150000)) + (10 * (1+0.150000)* (1+0.150000) *(1+0.150000)) )
我知道我们可以使用递归CTE来做到这一点,因为我必须为超过500万条记录执行此操作,因此效率不高。
我希望实现类似于基于集合的方法
对于ccp :ccp1
SELECT col3 - ( col1 * ( 1 + col4 ) )
FROM #Table1
WHERE rno = 1
SELECT rno,
col3 - ( ( col1 * Power(( 1 + col4 ), 1) ) + ( Lag(col1, 1)
OVER(
ORDER BY rno ) * Power(( 1 + col4 ), 2) ) )
FROM #Table1
WHERE rno IN ( 1, 2 )
SELECT rno,
col3 - ( ( col1 * Power(( 1 + col4 ), 1) ) + ( Lag(col1, 1)
OVER(
ORDER BY rno ) * Power(( 1 + col4 ), 2) ) + ( Lag(col1, 2)
OVER(
ORDER BY rno ) * Power(( 1 + col4 ), 3) ) )
FROM #Table1
WHERE rno IN ( 1, 2, 3 )
有没有办法在单个查询中计算?
仍然愿意接受建议。我强烈相信应该有一些使用SUM () Over(Order by)
窗口聚合函数来做到这一点。
答案 0 :(得分:29)
最后,我使用以下方法获得了结果
gsub
结果:
SELECT a.*,
col3 - res AS Result
FROM #TABLE1 a
CROSS apply (SELECT Sum(b.col1 * Power(( 1 + b.COL2 / 100.00 ), new_rn)) AS res
FROM (SELECT Row_number()
OVER(
partition BY ccp
ORDER BY rno DESC) new_rn,*
FROM #TABLE1 b
WHERE a.ccp = b.ccp
AND a.rno >= b.rno)b) cs
答案 1 :(得分:10)
这个答案可能令人失望,但您可能会发现迭代CLR方法与任何TSQL方法都具有竞争优势。
尝试以下操作(基于Running sums yet again: SQLCLR saves the day!)
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void StackoverflowQuestion41803909()
{
using (SqlConnection conn = new SqlConnection("context connection=true;"))
{
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
comm.CommandText = @"
SELECT [rno],
[ccp],
[col1],
[col2],
[col3],
[col4]
FROM Table1
ORDER BY ccp,
rno
";
SqlMetaData[] columns = new SqlMetaData[7];
columns[0] = new SqlMetaData("rno", SqlDbType.Int);
columns[1] = new SqlMetaData("ccp", SqlDbType.VarChar, 50);
columns[2] = new SqlMetaData("col1", SqlDbType.Int);
columns[3] = new SqlMetaData("col2", SqlDbType.Int);
columns[4] = new SqlMetaData("col3", SqlDbType.Int);
columns[5] = new SqlMetaData("col4", SqlDbType.Decimal, 17, 6);
columns[6] = new SqlMetaData("result", SqlDbType.Decimal, 17, 6);
SqlDataRecord record = new SqlDataRecord(columns);
SqlContext.Pipe.SendResultsStart(record);
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
string prevCcp = null;
decimal offset = 0;
while (reader.Read())
{
string ccp = (string)reader[1];
int col1 = (int)reader[2];
int col3 = (int)reader[4];
decimal col4 = (decimal)reader[5];
if (prevCcp != ccp)
{
offset = 0;
}
offset = ((col1 + offset) * (1 + col4));
record.SetInt32(0, (int)reader[0]);
record.SetString(1, ccp);
record.SetInt32(2, col1);
record.SetInt32(3, (int)reader[3]);
record.SetInt32(4, col3);
record.SetDecimal(5, col4);
record.SetDecimal(6, col3 - offset);
SqlContext.Pipe.SendResultsRow(record);
prevCcp = ccp;
}
SqlContext.Pipe.SendResultsEnd();
}
}
};
答案 2 :(得分:5)
另一个选择
<img id="album_cover" src="space-160x160.jpg" alt="Kalliope Image">
const albumCover = document.querySelector("#album_cover");
songPick.addEventListener("change", audioImageSource);
function audioImageSource() {
let option = document.querySelector("select").options;
let indexImageSong = document.querySelector("select").selectedIndex;
audio.src = songPick.value;
console.log(option[indexImageSong].index);
console.log(option[indexImageSong]);
switch (option[indexImageSong].index) {
case 0:
console.log(albumCover);
albumCover.src = 'space-160x160.jpg';
break;
case 1:
albumCover.src = 'friendly-alien-planet-160x160.jpg';
break;
case 2:
albumCover.src = 'Soundscape-music-160x160.jpg';
break;
case 3:
albumCover.src = 'soundscape-160x160.jpg';
break;
}
}
答案 3 :(得分:4)
cross apply
的方法。不确定这是否比使用WITH T AS
(SELECT *,
ROW_NUMBER() OVER(PARTITION BY CCP
ORDER BY RNO) AS RN
FROM #TABLE1)
SELECT T1.RNO,
T1.CCP,
T1.COL1,
T1.COL2,
T1.COL3,
T1.COL3-SUM(T2.COL1*POWER(1+T1.COL2/100.0,T1.RN-T2.RN+1)) AS RES
FROM T T1
JOIN T T2 ON T1.CCP=T2.CCP
AND T1.RN>=T2.RN
GROUP BY T1.RNO,
T1.CCP,
T1.COL1,
T1.COL2,
T1.COL3
的版本更有效。
sendSpecialChat
答案 4 :(得分:3)
试试这个:
;with
val as (
select
*,
(1 + col2 / 100.00) val,
row_number() over(partition by ccp order by rno desc) rn
from #Table1),
res as (
select
v1.rno,
--min(v1.ccp) ccp,
--min(v1.col1) col1,
--min(v1.col2) col2,
min(v1.col3) col3,
sum(v2.col1 * power(v2.val, 1 + v2.rn - v1.rn)) sum_val
from val v1
left join val v2 on v2.ccp = v1.ccp and v2.rno <= v1.rno
group by v1.rno)
select *, col3 - isnull(sum_val, 0)
from res
但性能取决于索引。发布索引结构以获取详细信当您将其拆分为更多临时表时,可以实现最佳性能。
答案 5 :(得分:2)
在玩了一段时间之后,我相信对于是否可以用sum() over (order by)
来完成这个问题的答案的答案是否定的。这段代码尽可能接近:
select *, col3 - sum(col1 * power(1 + col4, row_num)) over (partition by ccp order by col1)
from (
select *, row_number() over (partition by ccp order by rno asc) row_num
from @Table1
) a
order by 1,2;
这将返回每个ccp
组中第一行的正确结果。通过使用rno desc
计算row_num,然后每个ccp
中的最后一行将是正确的。
似乎只有通过语法建议的简单方式才能使其工作的唯一方法是:
窗口函数不能在另一个窗口的上下文中使用 功能或聚合。
这是一个有趣的问题。我很好奇这个解决方案如何对大数据集执行,即使实际结果不正确。