Как правильно написать этот запрос с помощью Amazon RedShift? - PullRequest
0 голосов
/ 30 апреля 2019

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

update fact_spv_commissioned_lot
set sn_count = fact_spv_commissioned_lot.sn_count + 
(
  SELECT COUNT(*) FROM staging_serials s
  JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
  JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
  JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
  JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
  WHERE c.sk_company_id = f.sk_company_id
  AND s.lotnumber = f.lot_number
  AND p.sk_product_id = f.sk_product_id
  AND l.sk_packaging_level_id = f.sk_packaging_level_id
)

или это правильный способ написать это?

update fact_spv_commissioned_lot
set sn_count = fact_spv_commissioned_lot.sn_count + 
(
  SELECT COUNT(*) FROM staging_serials s
  JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
  JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
  JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
  JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
  WHERE c.sk_company_id = f.sk_company_id
  AND s.lotnumber = f.lot_number
  AND p.sk_product_id = f.sk_product_id
  AND l.sk_packaging_level_id = f.sk_packaging_level_id
)
FROM staging_serials s
  JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
  JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
  JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
  JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
  WHERE c.sk_company_id = f.sk_company_id
  AND s.lotnumber = f.lot_number
  AND p.sk_product_id = f.sk_product_id
  AND l.sk_packaging_level_id = f.sk_packaging_level_id

или это правильный способ написать это?

update fact_spv_commissioned_lot
set sn_count = fact_spv_commissioned_lot.sn_count + 
(
  SELECT COUNT(*) FROM staging_serials s
  JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
  JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
  JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
  JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
)
  WHERE c.sk_company_id = f.sk_company_id
  AND s.lotnumber = f.lot_number
  AND p.sk_product_id = f.sk_product_id
  AND l.sk_packaging_level_id = f.sk_packaging_level_id

1 Ответ

1 голос
/ 30 апреля 2019

Мне лично нравятся CTE , но ваш первый запрос почти готов.

Версия CTE будет выглядеть следующим образом (замените <pk-col> фактическим столбцом первичного ключа):

WITH
    agg_data (pk, count) AS (
        SELECT f.<pk-col>, COUNT(*)
        FROM staging_serials s
            JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
            JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
            JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
            JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
        WHERE c.sk_company_id = f.sk_company_id
            AND s.lotnumber = f.lot_number
            AND p.sk_product_id = f.sk_product_id
            AND l.sk_packaging_level_id = f.sk_packaging_level_id
        GROUP BY 1
    )
UPDATE fact_spv_commissioned_lot AS to_update
SET sn_count = sn_count + agg_data.count
FROM agg_data WHERE agg_data.pk = to_update.<pk-col>;

В качестве альтернативы вы также можете использовать исходные столбцы соединения из вашего подвыбора, связанные с таблицей fact_spv_commissioned_lot, чтобы составить корреляцию с удаленным JOIN (f), например ::

WITH
    agg_data (sk_company_id, lot_number, sk_product_id, sk_packaging_level_id, count) AS (
        SELECT f.sk_company_id, f.lot_number, f.sk_product_id, f.sk_packaging_level_id, COUNT(*)
        FROM staging_serials s
            JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
            JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
            JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
            JOIN fact_spv_commissioned_lot f ON (f.sk_company_id = s.companyid)
        WHERE c.sk_company_id = f.sk_company_id
            AND s.lotnumber = f.lot_number
            AND p.sk_product_id = f.sk_product_id
            AND l.sk_packaging_level_id = f.sk_packaging_level_id
        GROUP BY 1, 2, 3, 4
    )
UPDATE fact_spv_commissioned_lot AS to_update
SET sn_count = sn_count + agg_data.count
FROM agg_data
WHERE agg_data.sk_company_id = to_update.sk_company_id
    AND agg_data.lot_number = to_update.lot_number
    AND agg_data.sk_product_id = to_update.sk_product_id
    AND agg_data.sk_packaging_level_id = to_update.sk_packaging_level_id
;

... или немного короче полностью со стилем sub-select:

UPDATE fact_spv_commissioned_lot AS to_update
SET sn_count = sn_count + (
    SELECT COUNT(*)
    FROM staging_serials s
        JOIN dim_md_company c ON (c.lsc_company_id = s.companyid)
        JOIN staging_product p ON (s.compositeproductcode = p.compositeproductcode)
        JOIN dim_packaging_level l ON (l.unit_of_measure = p.packaginguom)
    WHERE s.companyid = to_update.sk_company_id
        AND s.lotnumber = to_update.lot_number
        AND c.sk_company_id = to_update.sk_company_id
        AND p.sk_product_id = to_update.sk_product_id
        AND l.sk_packaging_level_id = to_update.sk_packaging_level_id
);

Если ваши таблицы средние и большие (от миллионов до миллиардов строк), CTE-версия также должна работать лучше (особенно в первом варианте с использованием столбца первичного ключа), хотя в SQL она немного более многословна.

...