Как извлечь значения из нормализованной структуры MySQL 5.7, которые соответствуют определенным критериям - PullRequest
0 голосов
/ 01 января 2019

Я пытаюсь нормализовать мою схему данных MySQL 5.7 и пытаюсь заменить запросы SQL:

В настоящее время существует одна таблица, содержащая все атрибуты каждой статьи:

article_id | title | ref_id | dial_c_id

Задача состоит в том, чтобы получить все статьи, которые соответствуют двум заданным атрибутам (ref_id и dial_c_id), а также получить все их другие атрибуты.

С одной таблицей это просто:

SELECT *
    FROM test.articles_test
WHERE
    ref_id = '127712' 
    AND dial_c_id = 51 

Теперь, пытаясь нормализоваться, я создал вторую таблицу, в которой хранятся атрибуты каждой статьи, и удалил их встатьи таблицы:

таблица 1:

article_id | title 

таблица 2:

article_id | attr_group | attribute
1            ref_id       51
1            dial_c_id    33
1            another      5
2 ..

Я хочу получить все сведения о статье, включая атрибуты ALL которые соответствуют ref_id и dial_c_id с этими двумя таблицами shema.

Примерно так:

SELECT 
     a.article_id,
     a.title, 
     attr.*
FROM test.articles_test a
INNER JOIN attributes attr ON a.article_id = attr.article_id
     AND ref_id = '127712' 
     AND dial_c_id = 51 

Как это можно сделать?

1 Ответ

0 голосов
/ 01 января 2019

Вы использовали таблицу Entity-Attribute-Value для записи своих атрибутов.

Это напротив нормализации.

Назовите правило нормализации, которое помогло вам поместить разные атрибуты в один столбец. Вы не можете, потому что это не нормализационная практика.

Чтобы выполнить ваш запрос с вашим текущим дизайном EAV, вам нужно повернуть результат, чтобы вы получили что-то, как если бы вы имелиисходная таблица.

SELECT * FROM (
    SELECT 
         a.article_id,
         a.title, 
         MAX(CASE attr_group WHEN 'ref_id' THEN attribute END) AS ref_id,
         MAX(CASE attr_group WHEN 'dial_c_id' THEN attribute END) AS dial_c_id
         -- ...others...
    FROM test.articles_test a
    INNER JOIN attributes attr ON a.article_id = attr.article_id
    GROUP BY a.article_id, a.title) AS pivot
WHERE pivot.ref_id = '127712' 
  AND pivot.dial_c_id = 51 

Хотя приведенный выше запрос может дать желаемый результат, производительность будет ужасной.Он должен создать временную таблицу для подзапроса, содержащую все данные из обеих таблиц , затем применить предложение WHERE к временной таблице.

Вам действительно лучше с каждым атрибутом всвой собственный столбец в исходной таблице.


Я понимаю, что вы пытаетесь учесть многие атрибуты в будущем.Это обычная проблема.

См. Мой ответ на Как составить таблицу продуктов для многих видов продуктов, где каждый продукт имеет много параметров

Но вы не должныНазовите это «нормализовано», потому что это не так.Это даже не денормализовано .Это дереляционно .

Вы не можете просто использовать слова, чтобы описать то, что вы хотите - особенно не то, что означает это слово.Я не могу выпустить воздух из моей велосипедной шины и сказать: «Я надуваю его».

Вы прокомментировали, что пытаетесь сделать вашу базу данных «масштабируемой».Вы также неправильно понимаете, что означает слово «масштабируемый».Используя EAV, вы создаете структуру, в которой необходимые запросы сложно писать и неэффективно выполнять, а данные занимают 10-кратное пространство. Это противоположность масштабируемой.

То, что вы имеете в виду, это то, что вы пытаетесь создать систему, расширяемую .Это сложно реализовать в SQL, но я опишу несколько решений в другом ответе переполнения стека, с которым я связан.Вам также может понравиться моя презентация Расширяемое моделирование данных с MySQL .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...