На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Akina
  
> Объединение данных из нескольких таблиц в одной.
    Есть таблица с множеством пользователей (в примере с одним).
    ExpandedWrap disabled
      CREATE TABLE `users`(`id` INT, `name` TEXT);
      INSERT `users`(`id`, `name`) VALUES (1, 'Vasily Pupkin');

    Существует неизвестное количество таблиц (в примере две) содержащих данные о пользователе.
    ExpandedWrap disabled
      CREATE TABLE `values_1`(`user_id` INT, `value_1` INT);
      INSERT `values_1`(`user_id`, `value_1`) VALUES (1, 1);
       
      CREATE TABLE `values_2`(`user_id` INT, `value_2` INT);
      INSERT `values_2`(`user_id`, `value_2`) VALUES (1, 2);

    Так можно получить фиксированное количество данных о пользователе.
    ExpandedWrap disabled
      SELECT `users`.`name`, `values_1`.`value_1`, `values_2`.`value_2` FROM `users` INNER JOIN `values_1`, `values_2`;

    Но, поскольку формат таблиц с данными одинаковый а их количество заранее не известно, то хотелось бы объединить таблицы с данными в одну, при этом добавив индекс данных (вроде как категория данных из соответствующей индексу таблицы).
    ExpandedWrap disabled
      CREATE TABLE `values`(`user_id` INT, `value` INT, `index` INT);
      INSERT `values`(`user_id`, `value`, `index`) VALUES (1, 1, 1), (1, 2, 2);

    Как составить запрос получения данных о пользователе аналогичный предыдущему, но работающий с объединённой таблицей?

    Я понимаю, что все данные можно затолкать вообще в одну таблицу, где будет имя пользователя и все его данные, но тогда у неё будет фиксированное число столбцов, а мне бы хотелось заводить новые категории данных (с новыми индексами) и при этом не трогать структуру таблиц.
    Сообщение отредактировано: RedLight -
      Цитата RedLight @
      но тогда у неё будет фиксированное число столбцов

      Немного неверное проектирование. Лучше, и гораздо проще, поступить вот как, с учетом:

      Цитата RedLight @
      поскольку формат таблиц с данными одинаковый

      Создаем таблицы:

      Users - таблица пользователей с полями Id и UserName
      Categories - таблица категорий данных с полями Id и CategoryName
      User2Categorу - таблица данных по категориям с полями UserId, CategoryId, Data

      Все. Теперь можно динамически добавлять категории данных, и можно пользователям "привязывать" данные по категориям.
      Другой вопрос - если захочется привязывать данные не одного типа (как сейчас по условию), а разных. Но это уже другой вопрос, требующий дальнейшей доработки. Там возможны варианты.
        Здесь `Data` из `User2Categorу` заменён на `SkillLevel`.
        ExpandedWrap disabled
          CREATE TABLE `Users`(`Id` INT, `UserName` TEXT);
          INSERT `Users`(`Id`, `UserName`) VALUES (1, 'Vasily Pupkin');
           
          CREATE TABLE `Categories`(`Id` INT, `CategoryName` TEXT);
          INSERT `Categories`(`Id`, `CategoryName`) VALUES (1, 'PHP Developers'), (2, 'English Speakers');
           
          CREATE TABLE `User2Categorу`(`UserId` INT, `CategoryId` INT, `SkillLevel` INT);
          INSERT `User2Categorу`(`UserId`, `CategoryId`, `SkillLevel`) VALUES (1, 1, 4), (1, 2, 3);

        Правильно ли я понял предложенный пример?
        Текстовые названия категорий в моём случае не нужны, хорошо бы их избежать.
        Предложенная `User2Categorу` выглядит как моя таблица `values` и так же не ясно как сделать запрос на выборку пользователя с его данными из неё.
        Имя пользователя, в принципе, тоже можно считать текстовыми данными, что бы рассмотреть пример с данными разных типов, так как ещё логин можно добавить, но пока не надо :) Таблица пользователей служебную информацию будет содержать, которая к данным не относится и всегда известны её количество и формат.
        Сообщение отредактировано: RedLight -
          Вы задаёте сразу несколько вопросов.

          Первый - как правильно хранить. На этот вопрос уже ответил Majestio - мы имеем типичную M:N связь между пользователями и и данными, и храним в формате, аналогичном EAV.

          Второй - как получить такие данные, если заранее не известно количество данных для одного пользователя. Тут ответ зависит от требуемого формата результата.

          Если он должен быть как показано в первом посте, то решение простое - используем UNION ALL и литералы для фиксации того, из какой таблицы выбраны данные.
          ExpandedWrap disabled
            SELECT *
            FROM main
            JOIN (
                SELECT '1' AS source, * FROM slave1
                UNION ALL
                SELECT '2', * FROM slave2
                UNION ALL
                ....
                ) AS slave ON ...

          Сложнее вариант, когда результат должен быть развёрнут в сводную таблицу, т.е. для каждого пользователя в результате должна быть только одна строка. В этом случае задачу решает использование динамического SQL в формате хранимой процедуры.
            Похоже без изучения теории не обойтись, буду читать про EAV до полного просветления :thanks:
              Цитата RedLight @
              Правильно ли я понял предложенный пример?

              В принципе - да. В приведенном тобою коде "заведены" две категории и один пользователь. И пользователю "привязаны" "скилы" по этим категориям.

              Цитата RedLight @
              Текстовые названия категорий в моём случае не нужны, хорошо бы их избежать.

              Названия категорий - некий аналог названий столбцов "плоской" таблицы. Не нужно этого избегать :) Но если уж избегать по-взрослому, тогда и имена пользователей нужно удалить, хватит их ID :lol:

              Цитата RedLight @
              и так же не ясно как сделать запрос на выборку пользователя с его данными из неё

              Если честно - проще пареной репы. Но нужно, чтобы ты подумал - это полезно на будущее. Ибо ...

              Цитата RedLight @
              Похоже без изучения теории не обойтись, буду читать про EAV до полного просветления

              Это правильное решение!
                Цитата RedLight @
                Похоже без изучения теории не обойтись

                Угу.

                Цитата RedLight @
                буду читать про EAV до полного просветления

                Особое внимание - области применения и недостаткам, а также альтернативам.
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0349 ]   [ 15 queries used ]   [ Generated: 27.04.24, 11:09 GMT ]