← Назад к вопросам

Приведи пример нормализованных данных

1.6 Junior🔥 201 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример нормализованных данных

Нормализация данных - это процесс организации данных в базе данных для снижения избыточности и улучшения целостности. Рассмотрим примеры от ненормализованного к нормализованному виду.

Пример 1: Неправильная структура (денормализованная)

# Плохо: данные дублируются
students = [
    {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "course": "Python",
        "course_code": "PY101",
        "instructor": "John",
        "instructor_email": "john@example.com",
        "instructor_phone": "+1-555-1234"
    },
    {
        "id": 2,
        "name": "Bob",
        "email": "bob@example.com",
        "course": "Python",
        "course_code": "PY101",
        "instructor": "John",
        "instructor_email": "john@example.com",
        "instructor_phone": "+1-555-1234"
    }
]

Проблемы:

  • Данные об инструкторе повторяются в каждом студенте
  • Если изменить email инструктора, придётся обновлять много записей
  • Много дублирования данных

Пример 2: Нормализованная структура (1НФ, 2НФ, 3НФ)

# Таблица Instructors
instructors = [
    {
        "instructor_id": 1,
        "name": "John",
        "email": "john@example.com",
        "phone": "+1-555-1234"
    }
]

# Таблица Courses
courses = [
    {
        "course_id": 1,
        "name": "Python",
        "code": "PY101",
        "instructor_id": 1
    }
]

# Таблица Students
students = [
    {
        "student_id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "course_id": 1
    },
    {
        "student_id": 2,
        "name": "Bob",
        "email": "bob@example.com",
        "course_id": 1
    }
]

# Таблица Enrollments (связь many-to-many)
enrollments = [
    {"enrollment_id": 1, "student_id": 1, "course_id": 1},
    {"enrollment_id": 2, "student_id": 2, "course_id": 1}
]

Преимущества:

  • Нет дублирования данных
  • Один инструктор - одна запись
  • Легко обновить email инструктора в одном месте
  • Легко добавлять новых студентов

Пример 3: SQL для нормализованной структуры

CREATE TABLE instructors (
    instructor_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100),
    phone VARCHAR(20)
);

CREATE TABLE courses (
    course_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    code VARCHAR(10) UNIQUE,
    instructor_id INT,
    FOREIGN KEY (instructor_id) REFERENCES instructors(instructor_id)
);

CREATE TABLE students (
    student_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100)
);

CREATE TABLE enrollments (
    enrollment_id INT PRIMARY KEY,
    student_id INT,
    course_id INT,
    FOREIGN KEY (student_id) REFERENCES students(student_id),
    FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

Пример 4: Python ORM с нормализованной структурой

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship

class Instructor(Base):
    __tablename__ = "instructors"
    
    instructor_id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    email = Column(String(100))
    phone = Column(String(20))
    
    courses = relationship("Course", back_populates="instructor")

class Course(Base):
    __tablename__ = "courses"
    
    course_id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    code = Column(String(10), unique=True)
    instructor_id = Column(Integer, ForeignKey("instructors.instructor_id"))
    
    instructor = relationship("Instructor", back_populates="courses")
    enrollments = relationship("Enrollment", back_populates="course")

class Student(Base):
    __tablename__ = "students"
    
    student_id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    email = Column(String(100))
    
    enrollments = relationship("Enrollment", back_populates="student")

class Enrollment(Base):
    __tablename__ = "enrollments"
    
    enrollment_id = Column(Integer, primary_key=True)
    student_id = Column(Integer, ForeignKey("students.student_id"))
    course_id = Column(Integer, ForeignKey("courses.course_id"))
    
    student = relationship("Student", back_populates="enrollments")
    course = relationship("Course", back_populates="enrollments")

Пример 5: Запрос нормализованных данных

# Получить всех студентов, записанных на курс "Python"
from sqlalchemy import select

query = select(Student).join(Enrollment).join(Course).filter(
    Course.name == "Python"
)
students = session.execute(query).scalars().all()

# Результат
for student in students:
    print(f"{student.name} - {student.email}")

# Получить курсы конкретного инструктора
query = select(Course).filter(
    Course.instructor.has(Instructor.name == "John")
)
courses = session.execute(query).scalars().all()

Уровни нормализации

1НФ (First Normal Form):

  • Атомарные значения в каждой ячейке (не массивы, не объекты)
  • Нет повторяющихся групп
# Плохо (2НФ нарушена)
student = {
    "id": 1,
    "name": "Alice",
    "courses": ["Python", "JavaScript"]  # Массив
}

# Хорошо (1НФ)
student = {"id": 1, "name": "Alice"}
courses = [
    {"course_id": 1, "student_id": 1, "name": "Python"},
    {"course_id": 2, "student_id": 1, "name": "JavaScript"}
]

2НФ (Second Normal Form):

  • Выполнена 1НФ
  • Все неключевые атрибуты полностью функционально зависят от первичного ключа
# Плохо
course = {
    "course_id": 1,
    "name": "Python",
    "instructor_name": "John",
    "instructor_email": "john@example.com"
}

# Хорошо
course = {
    "course_id": 1,
    "name": "Python",
    "instructor_id": 1
}

instructor = {
    "instructor_id": 1,
    "name": "John",
    "email": "john@example.com"
}

3НФ (Third Normal Form):

  • Выполнена 2НФ
  • Нет транзитивных зависимостей
# Плохо
student = {
    "id": 1,
    "name": "Alice",
    "course_id": 1,
    "course_name": "Python",
    "instructor_name": "John"
}

# Хорошо (отдельные таблицы для каждой сущности)
student = {"id": 1, "name": "Alice", "course_id": 1}
course = {"course_id": 1, "name": "Python", "instructor_id": 1}
instructor = {"instructor_id": 1, "name": "John"}

Практический пример из жизни

# Денормализованная схема (неправильно)
users_orders = [
    {
        "order_id": 1,
        "user_id": 1,
        "user_name": "Alice",
        "user_email": "alice@example.com",
        "product_id": 101,
        "product_name": "Laptop",
        "product_price": 999,
        "quantity": 1,
        "total": 999
    },
    {
        "order_id": 2,
        "user_id": 1,
        "user_name": "Alice",  # Дублирование
        "user_email": "alice@example.com",  # Дублирование
        "product_id": 102,
        "product_name": "Mouse",
        "product_price": 25,
        "quantity": 2,
        "total": 50
    }
]

# Нормализованная схема (правильно)
users = [
    {"user_id": 1, "name": "Alice", "email": "alice@example.com"}
]

products = [
    {"product_id": 101, "name": "Laptop", "price": 999},
    {"product_id": 102, "name": "Mouse", "price": 25}
]

orders = [
    {"order_id": 1, "user_id": 1}
]

order_items = [
    {"order_item_id": 1, "order_id": 1, "product_id": 101, "quantity": 1},
    {"order_item_id": 2, "order_id": 2, "product_id": 102, "quantity": 2}
]

Итоговые выводы

  1. Нормализация удаляет дублирование данных
  2. Облегчает обновление и поддержку данных
  3. Повышает целостность данных
  4. Требует больше JOIN операций при запросах
  5. Есть баланс между нормализацией и производительностью
  6. Иногда денормализация нужна для оптимизации скорости
Приведи пример нормализованных данных | PrepBro