У меня есть этот стол

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-1 или ItemRandom-2

Результат должен быть таким:

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

Как я могу этого достичь? Заранее спасибо и извините за мой английский.

0
YVS1102 28 Фев 2018 в 07:16

5 ответов

Лучший ответ

Вот один из способов. Сначала обновите таблицу с общим количеством для каждого 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
0
uzi 28 Фев 2018 в 04:58

Это один из способов достижения вашего результата:

SELECT MIN(item) AS item,
    SUM(qty) AS qty,
    fixitem
FROM #temp
GROUP BY fixitem;
0
Pham X. Bach 28 Фев 2018 в 04:22

Я понятия не имею, что вы ищете, но для экземпляра, когда вы хотите получить желаемый результат, вам понадобится GROUP BY предложение и использование функции min() для получения первого Item, не требуется удалить элемент.

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

Для меня удаление было бы ненужным действием, поскольку результат отображал бы сумму qty 7, но фактическое показывало бы другое, а не сумму 7 для ItemRandom-1

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
0
Yogesh Sharma 28 Фев 2018 в 04:40

Вы можете добиться этого с помощью запроса 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 = ''
0
Krupa 28 Фев 2018 в 05:29

Почему бы не использовать инструкцию 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.

0
Andrei Odegov 1 Мар 2018 в 05:55