Обновление столбца по результатам подсчета подзапроса - PullRequest
0 голосов
/ 07 ноября 2018

У меня следующий запрос:

SELECT count(distinct document_key), etl_telco_cycle.customer_number FROM telco_document_header inner join etl_telco_cycle on  (telco_document_header.customer_number like '%' || etl_telco_cycle.customer_number) where telco_document_header.document_cycle = substring(cast(now() - interval '1 month' as varchar) from 1 for 4) || substring(cast(now() - interval '1 month' as varchar) from 6 for 2) and telco_document_header.customer_number like '%' || etl_telco_cycle.customer_number) group by etl_telco_cycle.customer_number

, который возвращает это:

Result:

Теперь я хочу использовать этот результат для обновления счетчика в таблице, где customer_number совпадает. Я попробовал это:

update etl_telco_cycle set amount_mobilephone_numbers = (SELECT count(distinct document_key), etl_telco_cycle.customer_number FROM telco_document_header inner join etl_telco_cycle on  (telco_document_header.customer_number like '%' || etl_telco_cycle.customer_number) where telco_document_header.document_cycle = substring(cast(now() - interval '1 month' as varchar) from 1 for 4) || substring(cast(now() - interval '1 month' as varchar) from 6 for 2) group by etl_telco_cycle.customer_number)

, что приводит к этому:

Error:

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Вы можете просто использовать коррелированный подзапрос:

update etl_telco_cycle
    set amount_mobilephone_numbers = (SELECT count(distinct document_key)
                                      FROM telco_document_header tdh
                                      WHERE tdh.customer_number = etl_telco_cycle.customer_number AND 
                                            tdh.document_cycle = substring(cast(now() - interval '1 month' as varchar) from 1 for 4) || substring(cast(now() - interval '1 month' as varchar) from 6 for 2) 
                                    );

Я не уверен, почему ваша версия использует LIKE для сопоставления по номерам клиентов. Это кажется неловким, поэтому я убрал его.

Я также думаю, что логику даты можно написать более кратко, используя TO_CHAR():

update etl_telco_cycle
    set amount_mobilephone_numbers = (SELECT count(distinct document_key)
                                      FROM telco_document_header tdh
                                      WHERE tdh.customer_number = etl_telco_cycle.customer_number AND 
                                            tdh.document_cycle = TO_CHAR(now() - interval '1 month', 'YYYYDD')
                                     );
0 голосов
/ 07 ноября 2018

Используйте предложение FROM для команды UPDATE :

UPDATE etl_telco_cycle e
SET    amount_mobilephone_numbers = c.ct
FROM  (
   SELECT e.customer_number, count(distinct document_key) AS ct
   FROM   telco_document_header t
   JOIN   etl_telco_cycle       e ON  t.customer_number like '%' || e.customer_number
   WHERE  t.document_cycle = substring(cast(now() - interval '1 month' as varchar) from 1 for 4)
                          || substring(cast(now() - interval '1 month' as varchar) from 6 for 2)
   GROUP  BY 1
   ) c
WHERE e.customer_number = c.customer_number
AND   e.amount_mobilephone_numbers IS DISTINCT FROM c.ct;  --optional optimization

Несмотря на то, что вы также можете использовать коррелированный подзапрос, он, как правило, будет намного медленнее, запуская один запрос агрегации на целевую строку, в то время как этот запрос запускает одиночный запрос агрегации. И есть небольшая разница: если в коррелированном подзапросе, например, не найдено связанных строк, например, * Гордон показывает , столбец по-прежнему обновляется до NULL (что не удалось бы для столбцов, определенных NOT NULL), в то время как мой запрос делает ничего вместо этого (сохраняя старое значение). Вам нужно определить желаемое поведение.

Добавленный AND e.amount_mobilephone_numbers IS DISTINCT FROM c.ct предотвращает пустые обновления. Связанный:

Вы можете еще больше оптимизировать производительность подзапроса. Вам может не потребоваться DISTINCT или JOIN в подзапросе - вам нужно будет увидеть точные определения и ограничения таблицы. Похоже, вы можете заменить это в любом случае:

   substring(cast(now() - interval '1 month' as varchar) from 1 for 4)
|| substring(cast(now() - interval '1 month' as varchar) from 6 for 2)

с:

to_char(now() - interval '1 month', 'YYYYMM')

Либо зависит от текущей настройки timezone, что может быть нежелательно в угловых случаях.

И document_cycle должны быть date или integer, а не строковым типом ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...