Проверьте на двойные результаты и затем удалите строку в другой таблице, если нет ни одного - PullRequest
0 голосов
/ 05 сентября 2018

Я хочу создать сложный запрос, который выполняет следующие действия:

получить laptop, service, technician таблицы lst в соответствии с ноутбуком равно X (число)

из тех строк, которые вы получаете, удалите laptop (фактически не можете удалить, поэтому сделайте это null)

из тех же строк, возможно, у некоторых не было technician. Таким образом, это строки, которые теперь содержат только service, без laptop и без technician

Хитрая часть: оставьте все service этих строк.
Если они не найдены где-либо еще в таблице lst, будучи в паре с другими laptop или technician, перейдите в таблицу service и удалите эту строку. Затем вернитесь к lst и удалите все строки, которые имеют service, а не laptop или technician.
Если они найдены где-либо еще в таблице lst в паре с другими laptop или technician, то просто удалите все строки lst в lst, у которых есть service и нет laptop или technician

Пример

lst table
laptop service technician 
17     10      25
17     10      26
17      4      null
17      2      null
125     2      null

и мы выполним вышеприведенное, имея laptop = 17

становится

laptop service technician 
null     10      25
null     10      26
null      4      null
null      2      null
125       2      null

Строка № 3 должна быть удалена, потому что она не имеет technician и laptop. Кроме того, service 4 таблицы service необходимо удалить, поскольку в таблице lts больше нигде ничего не найти в паре с чем-либо.

Строка № 4 должна быть удалена, потому что она не имеет technician и laptop. Но service 2 таблицы service не будет удален, поскольку он находится в другом месте в lts, в паре с другим laptop (последняя строка)

Итак, lts теперь становится

laptop service technician 
null     10      25
null     10      26
125       2      null

и я только удаляю service 4 из таблицы service

Я пробовал несколько комбинаций запросов / подзапросов, например

select id , technician from lts where  laptop= 17 and  technician in(
  select id   from 
  lts 
  where id in
    (select id from lts where technician is null and  laptop = 17) 
);

Но ничего не работает, и ничто не может сохранить все идентификаторы, чтобы пойти и удалить из таблицы service, позже.

Полагаю, мне придется использовать функцию или транзакцию pl/pgsql, но даже с транзакцией я не знаю, как кратко сохранить идентификаторы для последующего удаления из таблицы service.

Есть идеи, как это сделать? Стратегия или базовый код?

Я использую Postgresql 10

Спасибо

1 Ответ

0 голосов
/ 06 сентября 2018

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

Запрос выглядит следующим образом (для демонстрации идеи - не проверено):

WITH potentially_orphan_services AS (
    SELECT service
    FROM lts
    WHERE laptop = X AND technician IS NULL
), deleted_services AS (
    DELETE FROM services
    WHERE service IN (
       SELECT service
       FROM potentially_orphan_services p
       WHERE NOT EXIST (
         SELECT 1
         FROM lts l
         WHERE laptop != X AND l.service = p.service
       )
), deleted_lts_without_technician AS (
   DELETE FROM lts
   WHERE laptop = X AND technician IS NULL
)
UPDATE lts
SET laptop = NULL
WHERE laptop = X AND technician IS NOT NULL
...