我有一个包含详细行的表。我们希望从此表中为聚合值进行事务处理。可能存在一种情况,其中一行为正,另一行为负。聚合为0.我想删除这些行。
以下是我的例子:
DECLARE @tmp TABLE ( orderid INT
, account INT
, vatid INT
, amount DECIMAL(10,2)
, vat DECIMAL(10,2) )
--test values
INSERT @tmp
VALUES ( 10001, 30500, 47, 175.50, 9.20 )
, ( 10001, 30501, 47, 2010.60, 18.30 )
, ( 10001, 30501, 47, 147.65, 8.05 )
, ( 10001, 30502, 47, 321.15, 18.40 )
, ( 10001, 30502, 47, 13.50, 0.95 )
, ( 10001, 30510, 40, 15.00, 0.0 )
, ( 10001, 30510, 40, -15.00, 0.0 )
--all rows
SELECT * FROM @tmp
--aggregate
--aggregate for account 30510 is 0
SELECT tmp.orderid
, tmp.account
, tmp.vatid
, SUM(tmp.amount) [totalamount]
, SUM(tmp.vat) [totalvat]
FROM @tmp tmp
GROUP BY tmp.orderid
, tmp.account
, tmp.vatid
--delete rows with aggregated values 0
DELETE tmp
FROM @tmp tmp
JOIN (
SELECT ag.orderid
, ag.account
, ag.vatid
FROM (
SELECT tmp.orderid
, tmp.account
, tmp.vatid
, SUM(tmp.amount) [totalamount]
, SUM(tmp.vat) [totalvat]
FROM @tmp tmp
GROUP BY tmp.orderid
, tmp.account
, tmp.vatid
) ag
WHERE ISNULL(ag.totalamount,0) = 0
AND ISNULL(ag.totalvat,0) = 0
) tmp2
ON tmp2.orderid = tmp.orderid
AND tmp2.account = tmp.account
AND tmp2.vatid = tmp.vatid
--check rows
SELECT * FROM @tmp
我的代码工作并删除聚合值为0的行。
但它看起来并不优雅。有没有更好的方法来实现相同的结果?
Greetings Reto
答案 0 :(得分:2)
delete tt
from ( select sum(t.vat) over (partition by t.orderid, t.account, t.vatid) as sumVat
, sum(t.amount) over (partition by t.orderid, t.account, t.vatid) as sumAmt
from @tmp t
) tt
where isnull(tt.sumAmt, 0) = 0
and isnull(tt.sumVat, 0) = 0
答案 1 :(得分:1)
试试这个
在较早阶段使用
HAVING
而不是在后期使用WHERE
。因此,查询将在分组级别过滤掉不需要的记录,并且仍会产生相同的结果。
--delete rows with aggregated values 0
DELETE tmp
FROM @tmp tmp
JOIN (
SELECT ag.orderid
, ag.account
, ag.vatid
FROM (
SELECT tmp.orderid
, tmp.account
, tmp.vatid
-- Removed unwanted aggregates from select clause here
FROM @tmp tmp
GROUP BY tmp.orderid
, tmp.account
, tmp.vatid
HAVING SUM(tmp.amount) = 0 -- This line is updated
AND SUM(tmp.vat) = 0 -- This line is updated
) ag
-- Removed WHERE clause from here and added HAVING above
) tmp2
ON tmp2.orderid = tmp.orderid
AND tmp2.account = tmp.account
AND tmp2.vatid = tmp.vatid
答案 2 :(得分:1)
我会使用公用表表达式来仅获取需要删除的行,然后使用内部联接从表中删除到按列分组的cte:
;WITH CTE AS
(
SELECT tmp.orderid
, tmp.account
, tmp.vatid
FROM @tmp tmp
GROUP BY tmp.orderid
, tmp.account
, tmp.vatid
HAVING SUM(tmp.amount) = 0
AND SUM(tmp.vat) = 0
)
DELETE t
FROM @Tmp as t
JOIN CTE ON t.orderid = cte.orderid
AND t.account = cte.account
AND t.vatid = cte.vatid