求和然后删除一行 - SQL Server 2008 R2

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求和然后删除一行 - SQL Server 2008 R2相关的知识,希望对你有一定的参考价值。

我有这张桌子

CREATE TABLE #temp
(
    Item VARCHAR(max),
    Qty DECIMAL(18,2),
    FixItem VARCHAR(max)
)

这是一些示例数据

INSERT INTO #temp (Item, Qty, FixItem)
VALUES ('ItemRandom-1', -- Item - varchar(max)
        2, -- Qty - decimal
        'ItemA'  -- FixItem - varchar(max)
       )

INSERT INTO #temp (Item, Qty, FixItem)
VALUES ('ItemRandom-2', -- Item - varchar(max)
        5, -- Qty - decimal
        'ItemA'  -- FixItem - varchar(max)
       )          

INSERT INTO #temp (Item, Qty, FixItem)
VALUES ('ItemRandom-3', -- Item - varchar(max)
        5, -- Qty - decimal
        'ItemB'  -- FixItem - varchar(max)
       ) 

INSERT INTO #temp (Item, Qty, FixItem)
VALUES ('ItemRandom-4', -- Item - varchar(max)
        5, -- Qty - decimal
        ''  -- FixItem - varchar(max)
       )        

INSERT INTO #temp (Item, Qty, FixItem)
VALUES ('ItemRandom-5', -- Item - varchar(max)
        5, -- Qty - decimal
        ''  -- FixItem - varchar(max)
       )          

选择它时,结果如下:

Item            Qty      FixItem
--------------------------------
ItemRandom-1    2.00     ItemA
ItemRandom-2    5.00     ItemA
ItemRandom-3    5.00     ItemB
ItemRandom-4    5.00     
ItemRandom-5    5.00     

我想组合FixItem所以我可以总结Qty,然后删除ItemRandom-1ItemRandom-2之间的一行

结果应该是这样的:

Item             Qty     FixItem
---------------------------------
ItemRandom-1     7.00     ItemA
ItemRandom-3     5.00     ItemB
ItemRandom-4     5.00     
ItemRandom-5     5.00     

我怎样才能做到这一点?提前致谢,对不起我的英语。

答案

这是一种方式。首先用每个FixItem的总数量更新您的表格。然后删除额外的行。

update a
    set a.Qty = b.Qty
from
    #temp a
    join (
        select
            FixItem, Qty = sum(Qty)
        from 
            #temp
        group by FixItem
    ) b on a.FixItem = b.FixItem

;with cte as (
    select *, rn = row_number() over (partition by FixItem order by Item) 
    from #temp
)

delete from cte
where rn > 1

select * from #temp

产量

Item            Qty     FixItem
--------------------------------
ItemRandom-1    7.00    ItemA
ItemRandom-3    5.00    ItemB

编辑:

update a
    set a.Qty = b.Qty
from
    #temp a
    join (
        select
            FixItem, Qty = sum(Qty)
        from 
            #temp
        where len(FixItem) > 0
        group by FixItem
    ) b on a.FixItem = b.FixItem

;with cte as (
    select *, rn = case when len(FixItem) > 0 then row_number() over (partition by FixItem order by Item) else 0 end
    from #temp
)

delete from cte
where rn > 1
另一答案

这是实现结果的一种方法:

SELECT MIN(item) AS item,
    SUM(qty) AS qty,
    fixitem
FROM #temp
GROUP BY fixitem;
另一答案

我不知道你在寻找什么但是对于实例作为期望的结果看你需要GROUP BY子句并使用min()函数来获得第一个Item,不需要删除该项目。

SELECT 
        MIN(Item) Item,
        SUM(Qty),
        FixItem
FROM #temp t
GROUP BY FixItem

对我来说删除将是不必要的操作,因为结果将显示qty 7的总和,但实际将显示另一个而不是为ItemRandom-1汇总7

DELETE t FROM
(
     SELECT *,
              ROW_NUMBER() OVER (PARTITION BY FixItem ORDER BY Item) Seq
     FROM #temp 
) t
WHERE Seq > 1

您可以使用窗口函数来实现结果

select  Item,
        SUM(Qty) OVER (ORDER BY FixItem  ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) Qty,
        FixItem 
from #temp
另一答案

您可以使用select查询来实现此目的,无需删除记录。对于此选择查询,您还可以创建视图以便于访问。

根据要求,您可以在项目列中放置最小值或最大值。

select min(item) item, SUM(qty) qty, fixitem from #temp 
where fixitem != '' group by fixitem
union all
select item, qty, fixitem from #temp 
where fixitem = ''
另一答案

为什么不使用MERGE声明?

CREATE TABLE #temp(
  Item VARCHAR(max),
  Qty DECIMAL(18,2),
  FixItem VARCHAR(max)
);

INSERT INTO #temp(Item, Qty, FixItem)
  VALUES
    ('ItemRandom-1', 2, 'ItemA'),
    ('ItemRandom-2', 5, 'ItemA'),
    ('ItemRandom-3', 5, 'ItemB'),
    ('ItemRandom-4', 5, ''),
    ('ItemRandom-5', 5, '');

WITH
  t AS (
    SELECT *,
      SUM(Qty)OVER(PARTITION BY FixItem) t,
      ROW_NUMBER()OVER(PARTITION BY FixItem ORDER BY Item) n
    FROM #temp
    WHERE FixItem != ''
  )
MERGE t USING (SELECT * FROM t WHERE n = 1) s
  ON t.Item = s.Item AND t.FixItem = s.FixItem AND t.n = s.n
WHEN MATCHED THEN UPDATE SET t.Qty = s.t
WHEN NOT MATCHED BY SOURCE THEN DELETE
OUTPUT $action, deleted.*;

SELECT * FROM #temp;

结果可以在rextester.com进行调查。

OUTPUT子句用于演示MERGE语句的功能。

以上是关于求和然后删除一行 - SQL Server 2008 R2的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:按分组列求和并按另一列排序

SQL Server CE 回滚不撤消删除

SQL Server 删除表的默认值约束

MSSQL sql server 2005/2008 row_number()函数应用之–删除表中重

从 SQL Server 表中删除一行

Query Sql Server 能够删除表的最后一行