Избегайте многократного поиска и повышения производительности
У меня есть случай, когда мне нужно сделать несколько соединений (поисков), как показано ниже запрос. Был приведен пример сценария.
У меня около 200 CAT_CODE. Я подумал о нескольких решениях и перечислил их как кейсы. Есть ли другой способ написания SQL-запроса для повышения производительности? или лучше подход в инструменте ETL?
Первичная таблица (PRIM):
NUM CAT1_CODE CAT2_CODE CAT3_CODE
A 1 y q
B 2 e a
C 3 s z
Вторичная таблица (LOV):
CATEGORY COLUMN_LKP EXT_CODE
CAT1_CODE 1 AB
CAT1_CODE 2 CD
CAT1_CODE 3 HI
CAT2_CODE y JL
CAT2_CODE e QD
CAT2_CODE s AH
CAT3_CODE q CD
CAT3_CODE a MS
CAT3_CODE z EJ
Случай 1: через SQL:
Я написал простой запрос для выполнения этой задачи. Как вы думаете, это был бы правильный подход? Есть ли другие способы улучшить этот запрос? Прямо сейчас я использую как Oracle, так и Postgres.
SELECT
NUM,
(SELECT EXT_CODE FROM TEST_LOV
WHERE CATEGRY='CAT1_CODE' AND COLUMN_LKP=A.CAT1_CODE) CAT1,
(SELECT EXT_CODE FROM TEST_LOV
WHERE CATEGRY='CAT2_CODE' AND COLUMN_LKP=A.CAT2_CODE) CAT2,
(SELECT EXT_CODE FROM TEST_LOV
WHERE CATEGRY='CAT3_CODE' AND COLUMN_LKP=A.CAT3_CODE) CAT3
FROM
TEST_PRIM A
ТРЕБУЕМЫЙ ВЫХОД:
NUM CAT1 CAT2 CAT3
A AB JL CD
B CD QD MS
C HI AH EJ
СЛУЧАЙ-2: ETL:
То же самое можно сделать через ETL. Нам нужно использовать поиск, чтобы сделать это.
Сценарий-1:
LOV(CAT1_CODE) LOV(CAT2_CODE) LOV(CAT3_CODE)
| | |
| | |
PRIM---->LOOKUP---------->LOOKUP------------>LOOKUP-------->TARGET
Я не думаю, что это был бы правильный подход. У нас есть 200 кодов, мы не можем использовать 200 поиска. Есть ли лучший подход для обработки этого в ETL(Datastage, Talend, BODS) с лучшей производительностью?
Сценарий-2:
Поворот PRIM(преобразование столбцов CAT1_CODE,CAT2_CODE,CAT3_CODE в строки), как показано ниже, и выполнение одного поиска. Но поворот займет много времени, потому что у нас есть данные около 600 миллионов и 200 столбцов.
NUM CATGRY CODE
A CAT1_CODE 1
A CAT1_CODE y
A CAT1_CODE q
B CAT2_CODE 2
B CAT2_CODE e
B CAT2_CODE a
C CAT3_CODE 3
C CAT3_CODE s
C CAT3_CODE z
Пожалуйста, предложите мне лучший способ справиться с этим подходом. Это может быть через ETL или через SQL. Заранее спасибо.
1 ответ
Вы можете использовать LATERAL
Ключевое слово, чтобы сделать магию, которую вы ищете.
Следующий код может помочь:
SELECT
NUM,
MAX(ext_code) FILTER (WHERE c.CATEGORY='CAT1_CODE') AS CAT1,
MAX(ext_code) FILTER (WHERE c.CATEGORY='CAT2_CODE') AS CAT2,
MAX(ext_code) FILTER (WHERE c.CATEGORY='CAT3_CODE') AS CAT3
FROM TEST_PRIM a
CROSS JOIN LATERAL (
SELECT *
FROM TEST_LOV b
WHERE
(a.CAT1_CODE=b.COLUMN_LKP AND B.CATEGORY = 'CAT1_CODE')
OR (a.CAT2_CODE=b.COLUMN_LKP AND B.CATEGORY = 'CAT2_CODE')
OR (a.CAT3_CODE=b.COLUMN_LKP AND B.CATEGORY = 'CAT3_CODE')
) c
GROUP BY NUM
ORDER BY NUM;
Выход
num | cat1 | cat2 | cat3
-----+------+------+------
A | AB | JL | CD
B | CD | QD | MS
C | HI | AH | EJ