Вопрос или проблема
Проблема:
У меня есть две таблицы в Snowflake: таблица dimension
с информацией об аккаунтах и таблица fact
, где номера аккаунтов встроены как часть строки в столбце PARAM_VALUE типа строка. Эти строки могут иметь различные форматы и разделители или вовсе не содержать разделителей, что усложняет извлечение номеров аккаунтов для объединения.
Я хочу извлечь и разложить номера аккаунтов из столбца PARAM_VALUE в таблице фактов, а затем объединить их с таблицей измерений для отображения соответствующих сведений об аккаунтах. Однако я не хочу полагаться на какой-либо конкретный разделитель или формат в PARAM_VALUE.
Таблица измерений содержит данные об аккаунтах:
Таблица измерений (account_dim)
Acc_no |
---|
8G4F2H1J9K |
4R6T8E3A1L |
9W5E2C7R4T |
1Q8N6F4G3H |
6M9R5E2C1A |
3K9P7R4G6T |
5E1C8R6T2H |
2T4R8G6F1N |
7H3G5E2C9R |
1L6T8R4E3A |
9R5E2C7K3G |
4F1N6H8R2T |
8G6T4R3E1C |
2H5E1C9R7K |
6T4R3G6F1N |
1C8R6T2H4G |
3R5E2C9K7H |
5T4R6G1F2E |
9K3G5E2C1R |
7R4G6T2H1L |
Apex Industries |
Nova Tech Solutions |
Global Finance Corp |
Eastern Logistics |
Western Digital Inc |
Cybernetic Systems |
Green Earth Energy |
Atlantic Healthcare |
Pacific Software |
Northern Lights Media |
Southern Comfort Foods |
Mountain View Ventures |
Valley Forge Investments |
Oceanic Exploration |
Sunset Properties |
Cityview Financial |
Riverside Manufacturing |
Skyline Advertising |
Brookside Realty |
Lakeside Construction |
Таблица фактов содержит миллиарды строк и выглядит так:
Таблица фактов (fact_table)
SQL_ID | OBJ_NAME | Param_Value |
---|---|---|
sql_id890890830492hjkhfdjkd899058390245 | customer_table (‘TN190423′,’TN80989073’) ,8G4F2H1J9K &niveiui | |
sql_id234567890123456789012345678901 | orders_table 788686786767%9W5E2C7R4T | jhjhjgjhg |
sql_id987654321098765432109876543210 | products_table (‘5T4R6G1F2E’,’4R6T8E3A1L’) AC9879879 | |
sql_id456789012345678901234567890123 | shipping_table (‘ Apex Industries | |
sql_id111111111111111111111111111111 | inventory_table ‘ 3K9P7R4G6T,4F1N6H8R2T’ TN0008989 | |
sql_id222222222222222222222222222222 | shipping_table (‘9W5E2C7R4T’,’1Q8N6F4G3H’) Eastern Logistics, Riverside Manufacturing | jkjkhkj |
sql_id333333333333333333333333333333 | returns_table ‘6M9R5E2C1A,3K9P7R4G6T’ ‘ 4R6T8E3A1L,’ | |
sql_id444444444444444444444444444444 | customers_table (‘5E1C8R6T2H’,’2T4R8G6F1N’) [ 6M9R5E2C1A , 2H5E1C9R7K ] | |
sql_id555555555555555555555555555555 | orders_table ‘7H3G5E2C9R,1L6T8R4E3A’ | |
sql_id666666666666666666666666666666 | products_table (‘3K9P7R4G6T’,’7897′) | |
sql_id777777777777777777777777777777 | inventory_table ‘9R5E2C7K3G,4F1N6H8R2T’ &&&8G6T4R3E1C AC8098908,AC465465 | |
sql_id678901234567890123456789012345 | customers_table Cityview Financial;; Oceanic Exploration | |
sql_id789012345678901234567890123456 | orders_table TN00098F1NBrookside Realty’ | |
sql_id890123456789012345678901234567 | products_table (‘6uyiyiuuitug’,’ 6T4R3G6F1N ‘) Apex Industries |
Ожидаемый результат:
Мне нужно извлечь шаблоны из столбца PARAM_VALUE в таблице fact_table с последующим поиском в таблице dim account_dim и разложить их по строкам таблицы фактов, создавая новую таблицу, подобную этой:
SQL_ID | OBJ_NAME | searched pattern |
---|---|---|
sql_id890890830492hjkhfdjkd899058390245 | customer_table | 8G4F2H1J9K |
sql_id234567890123456789012345678901 | orders_table | 9W5E2C7R4T |
sql_id987654321098765432109876543210 | products_table | 5T4R6G1F2E |
sql_id987654321098765432109876543210 | products_table | 4R6T8E3A1L |
sql_id456789012345678901234567890123 | shipping_table | Apex Industries |
sql_id456789012345678901234567890123 | shipping_table | 9K3G5E2C1R |
sql_id111111111111111111111111111111 | inventory_table | 4F1N6H8R2T |
sql_id111111111111111111111111111111 | inventory_table | 3K9P7R4G6T |
sql_id222222222222222222222222222222 | shipping_table | 9W5E2C7R4T |
sql_id222222222222222222222222222222 | shipping_table | 1Q8N6F4G3H |
sql_id222222222222222222222222222222 | shipping_table | Eastern Logistics |
sql_id222222222222222222222222222222 | shipping_table | Riverside Manufacturing |
sql_id333333333333333333333333333333 | returns_table | 6M9R5E2C1A |
sql_id333333333333333333333333333333 | returns_table | 3K9P7R4G6T |
sql_id333333333333333333333333333333 | returns_table | 4R6T8E3A1L |
sql_id444444444444444444444444444444 | customers_table | 5E1C8R6T2H |
sql_id444444444444444444444444444444 | customers_table | 2T4R8G6F1N |
sql_id444444444444444444444444444444 | customers_table | 6M9R5E2C1A |
sql_id444444444444444444444444444444 | customers_table | 2H5E1C9R7K |
sql_id555555555555555555555555555555 | orders_table | 7H3G5E2C9R |
sql_id555555555555555555555555555555 | orders_table | 1L6T8R4E3A |
sql_id666666666666666666666666666666 | products_table | 3K9P7R4G6T |
sql_id777777777777777777777777777777 | inventory_table | 9R5E2C7K3G |
sql_id777777777777777777777777777777 | inventory_table | 4F1N6H8R2T |
sql_id777777777777777777777777777777 | inventory_table | 8G6T4R3E1C |
sql_id678901234567890123456789012345 | customers_table | Cityview Financial |
sql_id678901234567890123456789012345 | customers_table | Oceanic Exploration |
sql_id789012345678901234567890123456 | orders_table | Brookside Realty |
sql_id890123456789012345678901234567 | products_table | Apex Industries |
sql_id890123456789012345678901234567 | products_table | 6T4R3G6F1N |
Аккаунты могут иметь разную длину и могут содержать как номер аккаунта, так и его название, и могут адаптироваться к любому формату. Поэтому разделение не должно производиться, так как они могут быть разделены или не разделены и могут использовать любые разделители между ними. Поэтому акцент делается на поиск в таблице измерений.
Я пробовал использовать следующий запрос REGEXP_LIKE для сопоставления и извлечения номеров аккаунтов. Однако этот запрос не возвращает никаких результатов. Нерегулярное форматирование столбца param_value, похоже, вызывает проблемы, и REGEXP_LIKE не находит совпадений надежно.
WITH flattened AS (
SELECT
f.sql_id,
f.obj_name,
a.Acc_No,
a.Acc_name
FROM
fact_table f
JOIN
account_dim a ON REGEXP_LIKE(UPPER(f.param_value), UPPER(a.Acc_No))
)
SELECT
sql_id,
obj_name,
Acc_No,
Acc_name
FROM
flattened;
Ответ или решение
Для извлечения и соединения переменных номерных аккаунтов из неструктурированных строк с использованием Snowflake, вы можете воспользоваться регулярными выражениями и функциями работы со строками, чтобы извлечь данные согласно представленной вами структуре таблиц.
Шаги решения
-
Создать временную таблицу для хранения извлечённых аккаунтов. Мы будем использовать CTE (Common Table Expression) для упрощения извлечения аккаунтов.
-
Использовать регулярные выражения для поиска номеров аккаунтов. Нам нужно создать регулярное выражение, которое неопределённо найдет номера аккаунтов из
PARAM_VALUE
, если они находятся в строке. - Объединить извлеченные данные с таблицей измерений. После извлечения аккаунтов, мы объединим их с таблицей
account_dim
, чтобы получить все соответствующие данные.
Пример запроса
Вот пример SQL-запроса, который можно использовать для решения данной задачи:
WITH extracted_accounts AS (
SELECT
f.sql_id,
f.obj_name,
TRIM(value) AS extracted_account
FROM
fact_table f,
LATERAL FLATTEN(INPUT => REGEXP_SPLIT_TO_ARRAY(UPPER(f.param_value), '[,\'()\\s]+')) AS value
WHERE
TRIM(value) IS NOT NULL AND TRIM(value) <> ''
),
matched_accounts AS (
SELECT
e.sql_id,
e.obj_name,
a.Acc_no AS matched_account
FROM
extracted_accounts e
JOIN
account_dim a ON e.extracted_account = UPPER(a.Acc_no)
)
SELECT
sql_id,
obj_name,
matched_account
FROM
matched_accounts
ORDER BY
sql_id, obj_name;
Пояснение запроса
-
extracted_accounts CTE:
- В этой части запроса мы используем функцию
REGEXP_SPLIT_TO_ARRAY
, чтобы разбить полеPARAM_VALUE
на массив строк, используя различные разделители, такие как запятые, пробелы и скобки. - С помощью
LATERAL FLATTEN
мы преобразуем массив строк в набор строк, что позволит нам извлекать каждое значение отдельно. - После этого мы убираем пустые или пробельные значения.
- В этой части запроса мы используем функцию
-
matched_accounts CTE:
- Здесь мы соединяем извлечённые аккаунты с таблицей
account_dim
, чтобы найти совпадения по номерам аккаунтов. Мы применяемUPPER()
для приведения всех значений к верхнему регистру, чтобы избежать проблем с регистром.
- Здесь мы соединяем извлечённые аккаунты с таблицей
- Финальный запрос:
- В этой части мы выбираем нужные поля из результатов, упорядоченные по
sql_id
иobj_name
.
- В этой части мы выбираем нужные поля из результатов, упорядоченные по
Заключение
Этот запрос позволит вам извлечь и соединить переменные номерные аккаунты из неструктурированных строк. Обязательно протестируйте его на ваших данных, поскольку могут понадобиться дополнительные корректировки для обработки специфических случаев в ваших строках PARAM_VALUE
.