求和然后删除一行 - SQL Server 2008 R2
Sum then delete one row - SQL Server 2008 R2
我有这个table
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)
)
这是 select 时的结果:
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-1
或 ItemRandom-2
之间的一行
结果应该是这样的:
Item Qty FixItem
---------------------------------
ItemRandom-1 7.00 ItemA
ItemRandom-3 5.00 ItemB
ItemRandom-4 5.00
ItemRandom-5 5.00
我怎样才能做到这一点?提前致谢,对不起我的英语。
这是实现结果的一种方法:
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
对我来说,删除是不必要的操作,因为结果会显示数量 7
的总和,但实际会显示另一个,而不是 ItemRandom-1
的总和 7
DELETE t FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY FixItem ORDER BY Item) Seq
FROM #temp
) t
WHERE Seq > 1
您可以使用 window 函数来实现结果
select Item,
SUM(Qty) OVER (ORDER BY FixItem ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) Qty,
FixItem
from #temp
这是一种方法。首先用每个 FixItem
的总数量更新您的 table。然后删除多余的行。
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查询实现,不需要删除记录。
对于此 select 查询,您还可以创建视图以便于访问。
根据需要,您可以在 Item 列中输入 Min 或 Max。
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 语句的功能。
我有这个table
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)
)
这是 select 时的结果:
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-1
或 ItemRandom-2
结果应该是这样的:
Item Qty FixItem
---------------------------------
ItemRandom-1 7.00 ItemA
ItemRandom-3 5.00 ItemB
ItemRandom-4 5.00
ItemRandom-5 5.00
我怎样才能做到这一点?提前致谢,对不起我的英语。
这是实现结果的一种方法:
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
对我来说,删除是不必要的操作,因为结果会显示数量 7
的总和,但实际会显示另一个,而不是 ItemRandom-1
7
DELETE t FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY FixItem ORDER BY Item) Seq
FROM #temp
) t
WHERE Seq > 1
您可以使用 window 函数来实现结果
select Item,
SUM(Qty) OVER (ORDER BY FixItem ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) Qty,
FixItem
from #temp
这是一种方法。首先用每个 FixItem
的总数量更新您的 table。然后删除多余的行。
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查询实现,不需要删除记录。 对于此 select 查询,您还可以创建视图以便于访问。
根据需要,您可以在 Item 列中输入 Min 或 Max。
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 语句的功能。