🧠 Ситуация
У тебя есть старая таблица пользователей:
users_old
---------
id
full_name -- "Ivan Petrov"
email
created_at
Новая схема БД требует нормализации:
users
------
id
first_name
last_name
email
created_at
profiles
--------
user_id
display_name -- оригинальное полное имя
⚠️ Проблема
В full_name данные грязные:
full_name
Ivan Petrov
Maria
John Smith Jr.
Anna-Marie Watson
Dmitry Ivanov
NULL
"" (пустая строка)
Требования миграции:
• Разбить имя на first_name и last_name
• Если фамилии нет → last_name = NULL
• Лишние пробелы убрать
• Суффиксы типа Jr. считать частью фамилии
• Пустые и NULL имена → first_name = 'Unknown'
• Оригинал имени сохранить в profiles.display_name
Миграция должна работать одним SQL-скриптом без Python
🎯 Задача
• Напиши SQL-миграцию, которая:
• Переносит данные из users_old в users
• Создаёт записи в profiles
• Чистит имя
• Работает корректно со всеми кейсами
💣 Усложнение (вот где ловушка)
• Таблица 10 млн строк, нельзя:
• Делать UPDATE по одной строке
• Использовать курсоры
• Только set-based SQL.
💡 Ожидаемое решение (PostgreSQL)
INSERT INTO users (id, first_name, last_name, email, created_at)
SELECT
id,
-- first_name
CASE
WHEN TRIM(full_name) IS NULL OR TRIM(full_name) = '' THEN 'Unknown'
ELSE split_part(TRIM(regexp_replace(full_name, '\s+', ' ', 'g')), ' ', 1)
END,
-- last_name
CASE
WHEN TRIM(full_name) IS NULL OR TRIM(full_name) = '' THEN NULL
WHEN array_length(string_to_array(TRIM(regexp_replace(full_name, '\s+', ' ', 'g')), ' '), 1) = 1
THEN NULL
ELSE substring(
TRIM(regexp_replace(full_name, '\s+', ' ', 'g'))
FROM position(' ' IN TRIM(regexp_replace(full_name, '\s+', ' ', 'g'))) + 1
)
END,
email,
created_at
FROM users_old;
INSERT INTO profiles (user_id, display_name)
SELECT
id,
NULLIF(TRIM(full_name), '')
FROM users_old;
Задача проверяет:
• работу со строками
• regexp_replace
• split_part
• edge cases
• производительность (set-based)
• реальную миграцию, а не учебный select
Post #1265
2.67K
- 👍 6
- 🔥 2
- ❤ 1