根据 sql select 查询 C# 的结果更新 table 列的最佳方法是什么?
What is the best way to update a table column based on a result of a sql select query C#?
原查询:
with Tr As (
SELECT
DocDtls.Warehouse,
Transactions.Code,
DocDtls.zDate,
Transactions.ID,
Transactions.QtyIn,
Transactions.QtyOut,
Transactions.BalanceAfter
FROM
DocDtls
INNER JOIN Transactions ON DocDtls.[PrimDocNum] = Transactions.[DocNum]
),
formatted_tr as (
select
ID,
Code,
QtyIn,
QtyOut,
BalanceAfter,
LAG(BalanceAfter, 1, 0) Over (
partition by Warehouse,
Code
order by
Code,zDate,ID
) Prev_BlncAfter
from
Tr
)
select ID,Code,QtyIn,QtyOut,BalanceAfter
,SUM(Prev_BlncAfter + QtyIn)-QtyOut As NewBlncAfter
from formatted_tr
group by ID,Code,QtyIn,QtyOut,BalanceAfter;
;
解释这个想法:
假设查询 returns Item X
的所有交易结果有 10 行,我需要遍历所有 10 行并设置 BalanceAfter
( 对于第一个交易 QtyIn
-QtyOut
, 任何其他交易 (PreviousBalanceAfter
+QtyIn)
-QtyOut
) 等等 .
我尝试过的:
我试图将查询结果放在 Datatable
中,然后使用 DataView
再次过滤它以获取 DataGridView
当前行 ID 的 NewBlncAfter
,因此 Dataview
只有一行并将其保存在一个变量中 - 到目前为止工作良好 - 当我尝试遍历 DataGridview
中的所有行并更新 BalanceAfter 我得到时:
Must Declare Scalar Variable @Newblnc
您可以在此处找到完整代码:
My Code
那么有没有一种直接的方法可以将所有交易的 BalanceAfter 更新为等于
编辑 #1:我使用了@Charliface 查询,结果是:
我使用旧查询来比较结果,BalanceAfter
应该在每一行中等于 NewBlncAfter
。
编辑 #2:使用 SUM
而不是 LAG
会导致计算错误,如果我多次使用查询,BalanceAfter
中的结果会成倍增加
ID Code QtyIn QtyOut BalanceAfter
9 100001 20000 0 20000
14 100001 0 6000 40000
21 100001 3500 0 60000
24 100001 0 3000 80000
主要思想和期望的结果例如:
ID Code QtyIn QtyOut BalanceAfter
9 100001 20000 0 20000
14 100001 0 6000 14000
21 100001 3500 0 17500
24 100001 0 3000 14500
公式为:
对于第一笔交易 QtyIn
-QtyOut
,任何其他交易 (PreviousBalanceAfter
+QtyIn)
-QtyOut
等等。
首先,我认为完全没有理由将所有这些数据拉入 C#,然后更新 row-by-row(这是非常低效的)。您可以在单个批量更新中执行此操作。
不太清楚你想要什么结果,但你似乎只想分配一个 运行 SUM
计算,而不是 LAG
.
此外:
- 第二个 CTE 是不必要的,可以折叠到第一个。
- 按
OVER
中的同一列进行分区和排序毫无意义。
- 最后的
GROUP BY
也没有任何意义而且看起来没有必要,因为您是按主键分组的。
WITH Tr AS (
SELECT
d.Warehouse,
t.Code,
d.zDate,
t.ID,
t.QtyIn,
t.QtyOut,
t.BalanceAfter,
SUM(t.QtyIn - t.QtyOut) OVER (
PARTITION BY d.Warehouse, t.Code
ORDER BY d.zDate, t.ID
ROWS UNBOUNDED PRECEDING
) BlncAfter
FROM
DocDtls d
INNER JOIN Transactions t ON d.PrimDocNum = t.DocNum
WHERE t.Code = @VariableCode
)
UPDATE Tr
SET BalanceAfter = BlncAfter;
最后一点:为什么要把这些信息存储在一个新列中呢?为什么不在需要时使用 SUM OVER
来计算它?
原查询:
with Tr As (
SELECT
DocDtls.Warehouse,
Transactions.Code,
DocDtls.zDate,
Transactions.ID,
Transactions.QtyIn,
Transactions.QtyOut,
Transactions.BalanceAfter
FROM
DocDtls
INNER JOIN Transactions ON DocDtls.[PrimDocNum] = Transactions.[DocNum]
),
formatted_tr as (
select
ID,
Code,
QtyIn,
QtyOut,
BalanceAfter,
LAG(BalanceAfter, 1, 0) Over (
partition by Warehouse,
Code
order by
Code,zDate,ID
) Prev_BlncAfter
from
Tr
)
select ID,Code,QtyIn,QtyOut,BalanceAfter
,SUM(Prev_BlncAfter + QtyIn)-QtyOut As NewBlncAfter
from formatted_tr
group by ID,Code,QtyIn,QtyOut,BalanceAfter;
;
解释这个想法:
假设查询 returns Item X
的所有交易结果有 10 行,我需要遍历所有 10 行并设置 BalanceAfter
( 对于第一个交易 QtyIn
-QtyOut
, 任何其他交易 (PreviousBalanceAfter
+QtyIn)
-QtyOut
) 等等 .
我尝试过的:
我试图将查询结果放在 Datatable
中,然后使用 DataView
再次过滤它以获取 DataGridView
当前行 ID 的 NewBlncAfter
,因此 Dataview
只有一行并将其保存在一个变量中 - 到目前为止工作良好 - 当我尝试遍历 DataGridview
中的所有行并更新 BalanceAfter 我得到时:
Must Declare Scalar Variable @Newblnc
您可以在此处找到完整代码: My Code
那么有没有一种直接的方法可以将所有交易的 BalanceAfter 更新为等于
编辑 #1:我使用了@Charliface 查询,结果是:
我使用旧查询来比较结果,BalanceAfter
应该在每一行中等于 NewBlncAfter
。
编辑 #2:使用 SUM
而不是 LAG
会导致计算错误,如果我多次使用查询,BalanceAfter
中的结果会成倍增加
ID Code QtyIn QtyOut BalanceAfter
9 100001 20000 0 20000
14 100001 0 6000 40000
21 100001 3500 0 60000
24 100001 0 3000 80000
主要思想和期望的结果例如:
ID Code QtyIn QtyOut BalanceAfter
9 100001 20000 0 20000
14 100001 0 6000 14000
21 100001 3500 0 17500
24 100001 0 3000 14500
公式为:
对于第一笔交易 QtyIn
-QtyOut
,任何其他交易 (PreviousBalanceAfter
+QtyIn)
-QtyOut
等等。
首先,我认为完全没有理由将所有这些数据拉入 C#,然后更新 row-by-row(这是非常低效的)。您可以在单个批量更新中执行此操作。
不太清楚你想要什么结果,但你似乎只想分配一个 运行 SUM
计算,而不是 LAG
.
此外:
- 第二个 CTE 是不必要的,可以折叠到第一个。
- 按
OVER
中的同一列进行分区和排序毫无意义。 - 最后的
GROUP BY
也没有任何意义而且看起来没有必要,因为您是按主键分组的。
WITH Tr AS (
SELECT
d.Warehouse,
t.Code,
d.zDate,
t.ID,
t.QtyIn,
t.QtyOut,
t.BalanceAfter,
SUM(t.QtyIn - t.QtyOut) OVER (
PARTITION BY d.Warehouse, t.Code
ORDER BY d.zDate, t.ID
ROWS UNBOUNDED PRECEDING
) BlncAfter
FROM
DocDtls d
INNER JOIN Transactions t ON d.PrimDocNum = t.DocNum
WHERE t.Code = @VariableCode
)
UPDATE Tr
SET BalanceAfter = BlncAfter;
最后一点:为什么要把这些信息存储在一个新列中呢?为什么不在需要时使用 SUM OVER
来计算它?