Какие существуют способы хранения списков в базе данных?

Здравствуйте! Я планирую загрузить данные из датафрейма pandas в базу данных MySQL. Вот структура данных: <br/> <pre><code class="python">all_data = {
    'Organization_name': [],
    'Organization_voen': [],
    'Organization_adress': [],
    'Event_name': [],
    'Event_number': [],
    'Classification_code': [],
    'Suggested_price': [],
    'Event_start_date': [],
    'Submission_deadline': [],
    'Envelope_opening_date': [],

    'Heading': [],
    'Disclosure': [],
    'Quantity': [],
    'Measure_unit': [],
    'Code': [],

    'Participation_fee': [],
    'Participation_description': [],

    'Usage_fee': [],
    'Usage_description': [],

    'Full_name': [],
    'Contact': [],
    'Position': [],
    'Phone_number': []
}</code></pre> <br/> <br/> Обратите внимание, что <pre><code class="python">'Heading': [],
'Disclosure': [],
'Quantity': [],
'Measure_unit': [],
'Code': []</code></pre> <br/> <br/> содержат серии pandas с вложенными списками строк, тогда как остальные поля представляют собой строки. Я успешно перенес столбцы с простыми строками, но возникли трудности с переносом данных из столбцов с вложенными списками. Как можно корректно перенести такие данные?
  • 10 сентября 2024 г. 23:23
Ответы на вопрос 2
Здравствуйте! Перенос данных из pandas DataFrame в базу данных MySQL, особенно когда дело касается вложенных списков, может быть задачей. Для успешного хранения таких данных в реляционной базе данных, как MySQL, вам стоит рассмотреть несколько подходов.

### Способы хранения вложенных данных в MySQL:

1. **Нормализация данных**:
   - Создайте отдельную таблицу для каждого вложенного списка. Например, вы можете создать таблицу для `Heading`, `Disclosure`, `Quantity`, и т. д. Каждая из этих таблиц будет ссылаться на основную таблицу (например, таблицу с организациями и событиями) с помощью внешнего ключа.
   - Пример структуры:
     - **organizations** (id, name, voen, address, ...)
     - **events** (id, organization_id, name, number, classification_code, ...)
     - **event_details** (id, event_id, heading, disclosure, quantity, measure_unit, code, ...)

2. **Хранение в формате JSON**:
   - Если вы используете MySQL 5.7 или новее, вы можете использовать тип данных `JSON` для хранения вложенных списков. В этом случае вы можете иметь столбец в таблице для хранения данных в формате JSON.
   - Пример:
     ```sql
     CREATE TABLE events (
         id INT AUTO_INCREMENT PRIMARY KEY,
         organization_id INT,
         name VARCHAR(255),
         details JSON
     );
     ```
   - Ваша колонка `details` может хранить данные таким образом: `{"Heading": [...], "Disclosure": [...], "Quantity": [...]}`.

3. **Форматирование в строки**:
   - Если объем данных не слишком велик, вы можете также рассмотреть возможность хранения вложенных списков в виде строковых представлений, например, используя разделитель (например, `;` или `,`).
   - Пример:
     - Вложенные данные могут храниться в виде строки: `"Heading1;Heading2;Heading3"`.

### Перенос данных из pandas DataFrame в MySQL:

Для переноса данных из вашего DataFrame в MySQL с учетом вложенных списков, вы можете воспользоваться библиотекой `SQLAlchemy` и `pandas`. Примерный алгоритм может выглядеть так:

```python
import pandas as pd
from sqlalchemy import create_engine

# Создание соединения с базой данных
engine = create_engine('mysql+pymysql://username:password@host/dbname')

# Преобразуем вложенные списки в формат JSON (если вы используете тип JSON в MySQL)
all_data['details'] = all_data.apply(lambda x: {
    'Heading': x['Heading'],
    'Disclosure': x['Disclosure'],
    'Quantity': x['Quantity'],
    'Measure_unit': x['Measure_unit'],
    'Code': x['Code']
}, axis=1)

# Сохранение основной информации в таблицу
main_df = pd.DataFrame({
    'Organization_name': all_data['Organization_name'],
    'Organization_voen': all_data['Organization_voen'],
    'Organization_adress': all_data['Organization_adress'],
    # Остальные поля по аналогии
})

main_df.to_sql('organizations', con=engine, if_exists='append', index=False)

# Сохранение данных с вложенными списками
details_df = pd.DataFrame({
    'event_id': main_df['id'],  # Предположим, id создан при загрузке
    'details': all_data['details'].to_json(orient='records')
})

details_df.to_sql('event_details', con=engine, if_exists='append', index=False)
```

### Вывод:

Выбор метода хранения данных зависит от объема данных и требований к производительности. Нормализация данных позволяет избежать дублирования и меньшее задание на размер хранилища, тогда как JSON предлагает гибкость. Рассмотрите все эти подходы и выберите наиболее подходящий для вашего случая.
Вложенные списки организуют классическую связь 1:N (одному блоку данных соответствует несколько записей из списка). 
Если эти строки списка как-то обрабатываются (поиск, фильтрация и пр.), то наиболее разумна схема с 2 таблицами и внешним ключом.
Если же списки только сохраняются и извлекаются, без вообще какой-либо обработки, то можно использовать предложенную mxelgin схему с хранением всего списка в одном поле TEXT либо JSON в сериализованном виде.
Похожие вопросы