Удалить / объединить строки на основе нескольких столбцов - PullRequest
1 голос
/ 04 мая 2020

У меня есть следующая таблица:

+------------+-----------+--------+----------+-------------+------------------+
|    id      |  order_id | origin | type     | delivery_id | return_requested | 
+------------+-----------+--------+----------+-------------+------------------+
| 42         | 420       |  US    | DELIVERY | d-UUID      |        0         |
+------------+-----------+--------+----------+-------------+------------------+
| 43         | 420       |  US    | RETURN   | r-UUID      |        1         |
+------------+-----------+--------+----------+-------------+------------------+
| 48         | 520       |  US    | DELIVERY | d-UUID      |        0         |
+------------+-----------+--------+----------+-------------+------------------+
| 50         | 520       |  US    | RETURN   | r-UUID      |        1         |
+------------+-----------+--------+----------+-------------+------------------+

Где d-UUID или r-UUID - уникальные идентификаторы с префиксом (d для доставки и r для возврата).

В настоящее время я изменил способ вставки данных в базу данных, и вместо того, чтобы каждый раз добавлять новую строку, теперь я нахожу order_id и обновляю существующую строку.

Например, если заказ был возвращен, я теперь найду тот, у которого id = 42, и обновлю его с типа 'ДОСТАВКА' до 'ВОЗВРАТ' и с return_requested 'с ложного на истинное, в то время как delivery_id остается то же. (два столбца type и return_requested немного избыточны, но это на другой день)

Но у меня сейчас много старых записей с delivery_id, начинающимися с r-, которые я хочу удалить / объединить с строки, где order_id одинаковы.

У меня есть следующее SQL, которое находит эти строки:

SELECT * FROM delivery
WHERE order_id IN (
    SELECT order_id FROM delivery
    WHERE return_requested = 1
    AND delivery_id LIKE '%R-%'
)

Но я не могу понять, как объединить эти строки. В конце я хочу добиться этого:

+------------+-----------+--------+----------+-------------+------------------+
|    id      |  order_id | origin | type     | delivery_id | return_requested | 
+------------+-----------+--------+----------+-------------+------------------+
| 42         | 420       |  US    | RETURN   | d-UUID      |        1         |
+------------+-----------+--------+----------+-------------+------------------+
| 48         | 520       |  US    | RETURN   | d-UUID      |        1         |
+------------+-----------+--------+----------+-------------+------------------+

EDIT: я зацикливался на операторе обновления / удаления, который изменяет данные в базе данных, а не на операторе SELECT.

Ответы [ 3 ]

0 голосов
/ 04 мая 2020

Вы можете использовать GROUP BY и агрегатные функции. Чтобы получить результат в виде одного вывода

ВЫБЕРИТЬ идентификатор_порядка, происхождение, тип, delivery_id, return_requested ОТ доставки, где группируются по Order_id, происхождение, тип, delivery_id, return_requested_id

0 голосов
/ 05 мая 2020

Есть ли у вас гарантия, что id поля delivery_id всегда больше текущего идентификатора, который вы хотите обновить, как показывает пример кода, и вы не возражаете против использования жестко закодированных значений в вашем SET предложение, вы можете использовать этот запрос:

UPDATE delivery
    SET  tipo = 'RETURN',
         return_requested = 1
WHERE order_id IN (
    SELECT order_id FROM delivery
    WHERE return_requested = 1 AND delivery_id = 'r-UUID'
    GROUP BY order_id, id
    HAVING id = max(id)
) AND tipo = 'DELIVERY'
0 голосов
/ 04 мая 2020

При условии, что не все заказы имеют возвраты, вам нужно объединение влево, чтобы получить желаемый результат:

SELECT
    o.id,
    o.order_id,
    o.origin,
    CASE WHEN r.id NULL THEN o.type ELSE r.type END AS type,
    o.delivery_id,
    CASE WHEN r.id NULL THEN 0 ELSE 1 END AS return_requested,
FROM delivery as o
LEFT JOIN delivery as r
    ON RIGHT(o.delivery_id, len(o.delivery_id)-2) = RIGHT(r.delivery_id, len(r.delivery_id)-2)

Чтобы "СЛИВАТЬ" записи, вы можете сделать это:

UPDATE o
SET 
    o.type = 'RETURN'
    o.return_requested = 1
from delivery as o
INNER JOIN delivery as r
    ON RIGHT(o.delivery_id, len(o.delivery_id)-2) = RIGHT(r.delivery_id, len(r.delivery_id)-2)

DELETE FROM delivery
WHERE LEFT(delivery_id, 2) = 'r-'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...