Есть таблица в MySQL содержащая, кроме всего прочего, два десятка столбцов со строковой информацией:
table (bla bla bla, string1, string2,…, string20)
Причем эти строки (string1, string2,…, string20) довольно длинные и часто повторяются в разных столбцах, что печально сказывается на объеме хранимых данных.
Естественно, сразу возникает желание разбить такую таблицу на две, в первой в соответствующих полях хранить идентификаторы строк из второй таблицы:
table1 (bla bla bla, id1, id2,…, id20)
table2 (id, string)
Но запросы на выборку данных из такой структуры получаются весьма громоздкими (с кучей JOIN).
Обычно построением таких запросов занимается обертка/слой над БД и это не вызывает дискомфорта, но к сожалению в этом проекте — лапшакод, который не хочется трогать, т.к. надо решить только задачу т.с. «компактизации» этой таблицы.
Я не силен в MySQL, но что-то подсказывает мне, что должен быть более удобный синтаксис подобных запросов или возможно эту задачу следует решать каким-то другим способом.
Подскажите пожалуйста как лучше это делать. Конечно если других вариантов нет, то и куча JOIN подойдет, но хотелось бы чего-то более изящного.
Если короче, то нужно избавляться от дублирования информации, создав новую таблицу, которая реализует связь «многие ко многим», и столбцы
[string1, string2,…, string20], [id1, id2,…, id20], превратит в записи
Дело в том, что отношение «много ко многим», как например между товарами-заказами здесь не совсем подходит, т.к. важно не просто наличие связи записи со строками, но и порядок следования этих строк, а также их постоянное количество, как если бы в каждом заказе должно быть ровно двадцать товаров и важно знать порядок в котором их заказали. Хотя может я вас не понял, могли бы вы объяснить немного подробнее?
Я бы заменил эту таблицу на отношение «Один ко многим»
Добавляем поле «номер», и через него контролируем порядок следования
Структура следующая:
main_table (id, bla bla bla)
и
detail_table (id, id_main_table, string, number)
Добавляем уникальный ключ на detail_table (id_main_table, number)
Для поддержки старого лапшакода нужно добавить VIEW TABLE1 основанный на
select m.*, d1.string string1, d2.string string2,… d20. string string20 from main_table m
left join detail_table d1 on d1.id = m.id_main_table and d1.number = 1
left join detail_table d2 on d2.id = m.id_main_table and d2.number = 2
…
left join detail_table d20 on d20.id = m.id_main_table and d2.number = 20
Не очень удачный вариант т.к. при таком подходе во второй таблице
detail_table (id, id_main_table, string, number)
будет куча дублей строк string, отличающихся только номерами id_main_table и/или number, а именно от этого я и хочу уйти!
Мой вариант, описанный в самом вопросе:
table1 (bla bla bla, id1, id2,…, id20)
table2 (id, string)
и запросом
select t.(bla bla bla), t1.string, t2.string,…, t20.string
from table1 t
left join table2 t1 on t1.id = t.id1
left join table2 t2 on t2.id = t.id2
…
left join table2 t20 on t20.id = t.id20
будет компактнее в плане хранения информации, да и работать такой запрос будет быстрее.
Именно такой view я пока и сделал.