Соединение трех таблиц, чтобы получить список тегов

0

У меня эти три таблицы:

user_submitted_value

  id | owner_id | value |
  -----------------------
   1 | 1        |  1337 |
   2 | 2        |  1337 |
   3 | 2        |  1337 |
   4 | 1        |  1337 |

тег

  id | owner_id |      text |
  ---------------------------
   1 | 1        |  'Tag 01' |
   2 | 1        |  'Tag 02' |
   3 | 1        |  'Tag 03' |
   4 | 2        |  'Tag 04' |

user_submitted_value_tag

  id | owner_id | tag_id | value_id |
  -----------------------------------
   1 | 1        |      1 |        1 |
   2 | 1        |      2 |        1 |
   3 | 1        |      3 |        1 |

Таким образом, пользователи могут отправлять значения и вводить любое количество тегов freetext для привязки к этому значению. Мне нужно хранить теги как принадлежащие определенному пользователю, и мне нужно уметь подсчитывать, сколько раз они использовали каждый тег.

Я хочу выполнить запрос, который получает строки из user_submitted_value с прикрепленными к ним тегами. Например:

  Query value with id 1:

  id | owner_id | value |                         tags |
  ------------------------------------------------------
   1 | 1        |  1337 | "'Tag 01','Tag 02','Tag 03'" |

  Query all values belonging to user with id 1:

  id | owner_id | value |                         tags |
  ------------------------------------------------------
   1 | 1        |  1337 | "'Tag 01','Tag 02','Tag 03'" |
   4 | 1        |  1337 |                           "" |

Я знаю, что мне нужно ПРИСОЕДИНЯЙСЯ один или несколько раз, но мне не достаточно удобно с SQL, чтобы выяснить, как именно.

Теги:
join
database-normalization

2 ответа

2
Лучший ответ

Это похоже на довольно скрытый формат данных, особенно потому, что owner_id повторяется во всех таблицах.

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

select usv.owner_id,
       group_concat(distinct usvt.value_id) as values,
       group_concat(distinct t.text) as tags
from user_submitted_value usv join
     user_submitted_value_tag usvt
     on usv.value_id = usvt.value_id and usv.owner_id = usvt.owner_id join
     tags t
     on usvt.tag_id = t.id and usvt.owner_id = t.owner_id
group by usv_owner_id;
  • 0
    Спасибо! Какие изменения вы бы предложили, чтобы формат данных был более эффективным?
  • 0
    Я нашел проблему с этим запросом. Он не будет возвращать значения без тегов. Отсутствие тегов допускает поведение в моем случае использования.
Показать ещё 2 комментария
0

Вот окончательное решение в моем случае. Сильно основывается на ответе Гордона Линоффа.

      SELECT
        user_submitted_value.id,
        user_submitted_value.creator_id,
        user_submitted_value.value,
        group_concat(tag.text) AS tags
      FROM user_submitted_value
      LEFT JOIN user_submitted_value_tag
        ON user_submitted_value.id = user_submitted_value_tag.value_id
        AND user_submitted_value.creator_id = user_submitted_value_tag.creator_id
      LEFT JOIN tag
        ON user_submitted_valuetag.tag_id = tag.id
        AND user_submitted_value_tag.creator_id = tag.creator_id
        WHERE user_submitted_value.id = ?
      GROUP BY user_submitted_value.id

Предложение WHERE во втором JOIN может быть изменено для получения всех значений для данного пользователя.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню