Sql删除语句麻烦

时间:2013-09-27 23:51:10

标签: sql sql-server

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

在下面的示例中,要删除的行将是第1行和第2行以及第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

希望这是有道理的,并感谢任何帮助。

4 个答案:

答案 0 :(得分:1)

试试这个:

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
)

答案 1 :(得分:1)

您可能希望将此问题分解为多个部分。

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

CREATE VIEW vw_foo AS
SELECT product,name, currency, sum(quantity) as net
FROM foo
GROUP BY product, name, currency
HAVING sum(quantity)=0;

此时,您需要确保此视图包含您希望删除的数据。在您的示例中,视图应该只有2条记录:ProductA / NameA / GBP和ProductA / NameB / USD

步骤2.删除字段匹配的数据:

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

答案 2 :(得分: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)

答案 3 :(得分:0)

我假设这是一个会计问题,在分类帐中抵消了一对条目。

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

我创建了一个临时测试表,用数据加载它,使用CTE - 公用表表达式 - 找到重复模式并将其连接到表中以选择行。

只需将'select *'更改为'delete'。

同样,这仅适用于相等的偏移对。它将导致奇数条目的破坏。

您是否只有偶数条目?

此致

约翰

-- 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;