Ответ
Для такой структуры данных я бы использовал три нормализованные таблицы с связями "один ко многим". Это исключает дублирование данных (например, названия марки для каждого автомобиля) и упрощает поддержку.
Схема БД (на примере PostgreSQL):
-- 1. Таблица марок (справочник)
CREATE TABLE brands (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
country VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 2. Таблица владельцев
CREATE TABLE owners (
id SERIAL PRIMARY KEY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 3. Таблица автомобилей
CREATE TABLE cars (
id SERIAL PRIMARY KEY,
vin VARCHAR(17) UNIQUE NOT NULL, -- Уникальный идентификатор
model VARCHAR(100) NOT NULL,
year INTEGER CHECK (year > 1900),
brand_id INTEGER NOT NULL REFERENCES brands(id) ON DELETE RESTRICT,
owner_id INTEGER NOT NULL REFERENCES owners(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Индексы для ускорения поиска
CREATE INDEX idx_cars_brand_id ON cars(brand_id);
CREATE INDEX idx_cars_owner_id ON cars(owner_id);
Пример запроса с JOIN в Node.js (используя pg):
const query = `
SELECT
c.vin,
c.model,
c.year,
b.name as brand_name,
o.first_name || ' ' || o.last_name as owner_name
FROM cars c
JOIN brands b ON c.brand_id = b.id
JOIN owners o ON c.owner_id = o.id
WHERE o.email = $1;
`;
const result = await pool.query(query, ['owner@example.com']);
Обоснование структуры:
ON DELETE RESTRICTдляbrand_id: Не позволяет удалить марку, если с ней связаны автомобили.ON DELETE CASCADEдляowner_id: При удалении владельца автоматически удаляются все его автомобили (логика может меняться в зависимости от требований).- Отдельная таблица
brands: Позволяет легко добавлять новые марки и изменять их данные в одном месте. Такая схема легко масштабируется, например, для добавления таблицыservice_visitsс внешним ключом наcars.id.