Как объединить две или более строк и СУММИРОВАТЬ столбец в ОБНОВЛЕНИИ без первичного ключа?

У меня есть такая таблица в SQL Server:

CTransaction CКоличество CItemCode ЦУОМ 001 2 0011 ПАКЕТ 001 5 0011 ПАКЕТ 001 1 0011 ПАКЕТ 002 3 0011 ПАКЕТ 002 3 0011 ПАКЕТ

По сути, эта таблица содержит сведения о товаре с соответствующим CTransaction. Я хочу объединить и обновить строки с одинаковыми CTransaction и CItemCode, суммируя их CQuantity.

После обновления в результате получится что-то вроде таблицы ниже...

CTransaction CКоличество CItemCode ЦУОМ 001 8 0011 ПАКЕТ 002 6 0011 ПАКЕТ

Я нашел аналогичный вопрос в здесь, однако пример включает первичный ключ. В моей таблице нет первичного ключа, и я понятия не имею, как это сделать. Возможно ли это вообще? Что я могу попробовать дальше?

Это было бы легко, если бы я просто собирал SELECT строки следующим образом:

SELECT 
    CTransaction, SUM(CQuantity), CItemCode, CUOM 
FROM 
    Table 
GROUP BY 
    CTransaction, CItemCode, CUOM

Но я не хочу этого. Я хочу обновить таблицу, чтобы навсегда удалить дубликаты.

Если это одноразовая вещь, просто создайте новую таблицу, а затем используйте INSERT INTO ..., а затем свой выбор.

Tim Biegeleisen 30.06.2024 04:41

@TimBiegeleisen Нет, я буду делать это периодически. Я не понимаю, что вы имеете в виду, говоря о создании новой таблицы и INSERT. Спасибо.

chris_techno25 30.06.2024 04:43

Просто создайте представление поверх этой таблицы.

Tim Biegeleisen 30.06.2024 04:45

Обратите внимание, что мы предпочитаем здесь технический стиль письма. Мы мягко не поощряем приветствия, «надеюсь, что вы сможете помочь», «спасибо», «заранее спасибо», благодарственные письма, приветы, добрые пожелания, подписи, «пожалуйста, можете ли вы помочь», материалы для болтовни и сокращенный txtspk, просьбы, как долго вы застрял, советы по голосованию, мета-комментарии и т. д. Просто объясните свою проблему и покажите, что вы пробовали, чего ожидали и что на самом деле произошло.

halfer 01.07.2024 00:57
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
4
102
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Каждая таблица должна иметь первичный ключ. В этом случае первичный ключ предположительно должен быть CTransaction, CItemCode, CUOM, и вам следует исправить процесс, чтобы обновить его, а не добавлять новые повторяющиеся строки.

Однако для этого можно использовать MERGE. Один из способов приведен ниже (обновить произвольный файл для каждой группы и удалить остальные).

WITH Tgt AS
(
SELECT *, 
        SumCQuantity = SUM(CQuantity) OVER (PARTITION BY CTransaction, CItemCode, CUOM ),
        rn = ROW_NUMBER() OVER (PARTITION BY CTransaction, CItemCode, CUOM  ORDER BY CTransaction) 
FROM YourTable
) 
Merge Tgt with (HOLDLOCK)
USING (VALUES(1)) src(rn) ON Tgt.rn = 1
WHEN MATCHED AND CQuantity IS DISTINCT FROM SumCQuantity THEN 
    UPDATE SET CQuantity = SumCQuantity 
WHEN NOT MATCHED BY SOURCE THEN 
    DELETE;

Скрипка

Или другая версия, предоставленная @Charlieface в комментариях (которая может быть более эффективной, поскольку позволяет избежать общей очереди подвыражений, вычисляя только текущую сумму - что можно сделать более потоковым способом, поскольку нет необходимости добавлять вычисленное значение вернуться к предыдущим строкам)

WITH target AS (
    SELECT *,
      SUM(t.CQuantity) OVER (PARTITION BY CTransaction, CItemCode ORDER BY CQuantity ROWS UNBOUNDED PRECEDING) AS TotalQty,
      LEAD(1) OVER (PARTITION BY CTransaction, CItemCode ORDER BY CQuantity) AS IsNotLast
    FROM YourTable t
)
MERGE target t
USING (VALUES(1)) AS v(dummy)
ON 1=1
WHEN MATCHED AND IsNotLast = 1 THEN DELETE
WHEN MATCHED AND CQuantity IS DISTINCT FROM TotalQty THEN
  UPDATE
    SET CQuantity = TotalQty;

Скрипка 2

Я понятия не имею, что вы только что сделали, но это работает как шарм. Большое спасибо. Мне придется изучить каждую часть вашего оператора SQL, чтобы мне не приходилось задавать подобные вопросы в будущем. Еще раз огромное спасибо.

chris_techno25 30.06.2024 05:15

@ chris_techno25 — он использует оконные функции/агрегаты для вычисления суммы по группе и применения последовательной нумерации строк внутри каждой группы. Вы можете увидеть результат здесь dbfiddle.uk/2yIceFym и MERGE просто обновляет строки, в которых был номер строки 1, и удаляет остальные (так как это будут нежелательные дубликаты)

Martin Smith 30.06.2024 05:18

Учитывая, что вы заявили, что вам может потребоваться периодическое объединение, вероятно, имеет смысл создать представление поверх исходной таблицы, используя уже созданный вами агрегатный запрос:

CREATE VIEW yourView AS
SELECT CTransaction, CItemCode, CUOM, SUM(CQuantity)
FROM yourTable
GROUP BY CTransaction, CItemCode, CUOM;

Тогда просто используйте SELECT * FROM yourView всякий раз, когда вам понадобится доступ к этим данным.

Другие вопросы по теме

Похожие вопросы

Левая часть выражения LIKE должна иметь значение varchar (фактически: varbinary). Какая альтернатива преобразованию varbinary в varchar?
Чтобы получить предыдущую запись, которая меньше заданной даты и времени
Выберите строки с тем же кодом товара, но с другим значением в другом столбце
Извлечение и обработка подстроки между различным количеством разделителей в строке переменной длины
Потеря производительности из-за бокового соединения в запросе Postgres
Есть ли способ эффективно поддерживать правила крупномасштабных данных в SQL?
Выберите минимум или максимум в зависимости от того, где существует повторяющееся значение
Как я могу пронумеровать экземпляр повторяющейся записи?
Разъяснение по поводу объединений
Как я могу избежать «ОШИБКИ: нет уникального ограничения, соответствующего заданным ключам для ссылочной таблицы» при ссылке на первичный ключ комбинации в Postgres?