Sql删除语句故障

Sql删除语句故障,sql,sql-server,Sql,Sql Server,我在编写一个脚本时遇到了问题,该脚本可以删除前三列上匹配的所有行,并且数量总和为零? 我认为查询需要找到所有匹配的产品,然后在该组中,所有匹配的名称,然后在该子集中,所有匹配的货币,然后是数量为零的货币 在下面的示例中,要删除的行是第1行和第2行、第4行和第6行 Product, Name, Currency, Quantity 1) Product A, Name A, GBP, 10 2) Product A, Name A, GBP, -10 3) Product A, Name B,

我在编写一个脚本时遇到了问题,该脚本可以删除前三列上匹配的所有行,并且数量总和为零? 我认为查询需要找到所有匹配的产品,然后在该组中,所有匹配的名称,然后在该子集中,所有匹配的货币,然后是数量为零的货币

在下面的示例中,要删除的行是第1行和第2行、第4行和第6行

Product, Name, Currency, Quantity

1) Product A, Name A, GBP, 10
2) Product A, Name A, GBP, -10
3) Product A, Name B, GBP, 10
4) Product A, Name B, USD, 10
5) Product A, Name B, EUR, 10
6) Product A, Name B, USD, -10
7) Product A, Name C, EUR, 10
希望这有意义,并感谢您的帮助。

尝试以下方法:

DELETE  
  FROM [Product]
 WHERE Id IN
(
SELECT Id
  FROM 
(
   SELECT Id, SUM(Quantity) OVER(PARTITION BY a.Product, a.Name, a.Currency) AS Sm
    FROM [Product] a

) a
WHERE Sm = 0
)

简化SQL的一种方法是将3列合并为一列并应用一些分组:

delete from product
where product + name + currency in (
    select product + name + currency
    from product
    group by product + name + currency
    having sum(quantity) = 0)

你可能想把这个问题分成几个部分

首先创建一个视图,列出总和为零的组合

CREATE VIEW vw_foo AS
SELECT product,name, currency, sum(quantity) as net
FROM foo
GROUP BY product, name, currency
HAVING sum(quantity)=0;
此时,您需要确保此视图包含您希望删除的数据。在您的示例中,视图应该只有两条记录:ProductA/NameA/GBP和ProductA/NameB/USD

第二步。删除字段匹配的数据:

DELETE FROM foo
WHERE EXISTS 
(SELECT *
FROM vw_foo
WHERE vw_foo.product = product
AND vw_foo.name = name
AND vw_currency = currency);

我假设这是一个会计问题,需要抵销分类账中的成对分录

例如,如果组合有三个条目(A、A、GBP),则此代码和上面的一些示例将不起作用

我创建了一个临时测试表,加载了您的数据,使用CTE(公共表表达式)来查找重复模式,并将其连接到表中以选择行

只需将“选择*”更改为“删除”

同样,这只适用于相等的偏移对。它将导致奇数个条目的混乱

您是否只有偶数个条目

诚恳

约翰


除非您添加一些约束,否则这就是子集和问题,这是NP-难的。总是有偏移行吗?例如,如果您的产品/名称货币有三个值-20、-10和30,该怎么办?它们都应该被删除,或者30的记录可能在等待-30吗?@Jerry,不应该有三行产品、名称和货币的值相同的情况。我喜欢它,而且它不仅仅是sql server。请注意,“foo”+“bar”很像“foob”+“ar”。匹配连接并不意味着匹配列。@哈波,我敢打赌OP的数据中没有冲突。谢谢波希米亚人,工作得很好!。虽然Habo提到的问题不应该是个问题,但为了以防万一,我在连接中添加了空格。
-- create sample table
create table #products
(
  product_id int identity(1,1),
  product_txt varchar(16), 
  name_txt varchar(16), 
  currency_cd varchar(16), 
  quantity_num int
);
go

-- add data 2 table
insert into #products
(product_txt, name_txt, currency_cd, quantity_num)
values
('A',  'A', 'GBP', 10),
('A',  'A', 'GBP', -10),
('A',  'B', 'GBP', 10),
('A',  'B', 'USD', 10),
('A',  'B', 'EUR', 10),
('A',  'B', 'USD', -10),
('A',  'C', 'EUR', 10);
go

-- show the data
select * from #products;
go

-- use cte to find combinations
with cte_Ledger_Offsets (product_txt, name_txt, currency_cd)
as
(
    select product_txt, name_txt, currency_cd
    from #products
    group by  product_txt, name_txt, currency_cd
    having sum(quantity_num) = 0
)
select * from #products p inner join cte_Ledger_Offsets c
on p.product_txt = c.product_txt and
p.name_txt = c.name_txt and 
p.currency_cd = c.currency_cd;