我使用Sql Server,我有一个返回的查询(我称之为@result) 每天特殊产品的所有输入(IN)和输出(OUT)数据 例如:
+---------+----------+---------+---------+
|RowID | Date | IN(+) | OUT(-) |
+---------+----------+---------+---------+
|100 |2001-01-01|50 |0 |
|101 |2001-01-02|20 |0 |
|102 |2001-01-03|0 |10 |
|103 |2001-01-04|0 |60 |
|104 |2001-01-05|15 |0 |
|105 |2001-01-06|35 |0 |
|106 |2001-01-07|0 |7 |
|107 |2001-01-08|0 |25 |
|108 |2001-01-09|0 |18 |
|109 |2001-01-10|50 |0 |
我使用此查询来计算查询中每个日期的保留值:
With cte1 as (
Select rowID,date,
(
SELECT SUM(in-out)
FROM @result T2 WHERE T2.rowid<=T1.rowid
) AS remain
From @result T1
)
Select * from cte1
+---------+----------+---------+---------+----------+
|RowID | Date | IN(+) | OUT(-) + remain +
+---------+----------+---------+---------+----------+
|100 |2001-01-01|50 |0 |50 |
|101 |2001-01-02|20 |0 |70 |
|102 |2001-01-03|0 |10 |60 |
|103 |2001-01-04|0 |60 |0 |
|104 |2001-01-05|15 |0 |15 |
|105 |2001-01-06|35 |0 |50 |
|106 |2001-01-07|0 |7 |43 |
|107 |2001-01-08|0 |25 |18 |
|108 |2001-01-09|0 |18 |0 |
|109 |2001-01-10|50 |0 |50 |
我想找到3个剩余字段等于零的最后一条记录,并将该字段(日期和id)保存在局部变量上。 注意:我对每件产品都有非常多的记录(大约数百万),所有产品的价值都很慢。
我使用此查询:
With cte1 as (
Select rowID,date,
(
SELECT SUM(in-out)
FROM @result T2 WHERE T2.rowid<=T1.rowid
) AS remain
From @result T1
)
Select cte1.RowID, cte1.Date
From cte1 Where mandeh = 0
order by cte1.rowID Desc
但这很慢。
问题:
是我查询找到零值的最佳方法,以及我可以采取哪些措施加快查询速度。
感谢。
=============================================== ========================== 这是数据表的结构
Create table TestSpeed
(
rowID int identity(1,1) PRIMARY KEY CLUSTERED,
G_date SmallDateTime,
G_Num integer,
in_data Numeric(18,2),
Out_data Numeric(18,2)
)
我导出此表的数据,您可以下载并导入数据到表中以获得测试查询速度。 Data For Import
我的最后一个返回特殊值的查询是:
With cte1 as (
Select rowID ,G_date,G_Num,in_data,Out_data ,
(
SELECT SUM(in_data-Out_data)
FROM Testspeed T2 WHERE T2.rowid<=T1.rowid
) AS Remain
From Testspeed T1
),
cte2 As
(
Select Top 3 * From cte1
Where Remain = 0
Order By rowid Desc
)
Select * From cte2
此查询在我的电脑上运行4分钟。
非常感谢
答案 0 :(得分:0)
我没有加载你的数据,而是一个大约1.5米行的样本。查询耗时约5秒,包括加载样本。
with cte as (
select rowID = max(rowID) + 1
, G_date = cast ( getdate() as SmallDateTime)
, In_calc = cast ( SUM(in_data) as numeric(18,2))
, Out_calc = cast ( SUM(out_data) as numeric(18,2))
, In_data = cast ( 0 as numeric(18,2))
, Out_data = cast ( 0 as numeric(18,2))
, Remain = cast ( SUM(in_data) - SUM(out_data) as numeric(18,2))
, Remain0 = 0
from @result
union all
select rowID = r.rowID
, G_date = r.G_date
, In_calc = cast ( cte.in_data - r.in_data as numeric(18,2))
, Out_calc = cast ( cte.out_data - r.out_data as numeric(18,2))
, In_data = cast ( cte.in_data as numeric(18,2))
, Out_data = cast ( cte.out_data as numeric(18,2))
, Remain = cast ( cte.in_data - cte.out_data as numeric(18,2))
, Remain0 = case when cte.in_data <= cte.out_data then cte.Remain0 + 1 else cte.Remain0 end
from @result r join cte on r.rowID=cte.rowID-1
where cte.Remain0 < 3
)
select * from cte where Remain0 between 1 and 3
option (maxrecursion=0) -- <-- if you need more than 100 recursion until you have 3 times zero
您从当前状态开始并逐行返回,In_data
和Out_data
是您拥有的金额,并且是计算Remain
的基础。
Remain0
计算你达到最低点的频率。