Объединение двух таблиц, где встречаются несколько совпадений, и создание текстового столбца для нескольких значений - PullRequest
1 голос
/ 17 января 2020

Как создать представление с text columnType с именем fileTags, значением которого является группировка всех экземпляров столбца fileTag. tag, imgId которого соответствует file. imgId? (Кроме того, в этом представлении будет гораздо больше объединений, чем в этом.)

Моя file таблица

+-------+----------+
| imgId | filename |
+-------+----------+
| 10    | dog.jpg  |
+-------+----------+
| 20    | cat.jpg  |
+-------+----------+
| 30    | bird.jpg |
+-------+----------+

Моя fileTag таблица

+----+--------+----------+
| id | tag    | imgId    |
+----+--------+----------+
| 1  | fur    | 10       |
+----+--------+----------+
| 2  | paw    | 10       |
+----+--------+----------+
| 3  | leash  | 10       |
+----+--------+----------+
| 4  | feline | 20       |
+----+--------+----------+

Моя намеченная цель. getFiles представление (Присоединитесь к imgId и создайте текстовый столбец, содержащий все метки)

+-------+----------+-----------------------+
| imgId | filename | fileTags              |
+-------+----------+-----------------------+
| 10    | dog.jpg  | ["fur","paw","leash"] |
+-------+----------+-----------------------+
| 20    | cat.jpg  | ["feline","litter"]   |
+-------+----------+-----------------------+
| 30    | bird.jpg | ["beak","wings"]      |
+-------+----------+-----------------------+

Моя попытка создания представления

SELECT
    `file`.`imgId` AS `imgId`,
     GROUP_CONCAT(`fileTag`.`tag`) AS `tags`
FROM
(
  `file`
    JOIN `fileTag` ON(
        (
            `file`.`imgId` = `fileTag`.`imgId`
        )
    )
)
GROUP BY `fileTag`.`imgId`

Моя проблема

  • Если я выполняю JOIN, производительность велика, но он возвращает только те строки, в которых у этого imgId есть fileTag. Мне нужно, чтобы все файлы возвращались, даже если у них нет fileTag.
  • Если я выполняю LEFT JOIN, производительность действительно плохая. Если я запускаю EXPLAIN, я вижу, что он индексирует слишком много строк для каждой таблицы. enter image description here

Любая помощь будет принята с благодарностью. Спасибо.

1 Ответ

3 голосов
/ 17 января 2020

Я думаю, что вы хотите LEFT JOIN:

SELECT f.imgId, GROUP_CONCAT(ft.tag) AS tags
FROM file f LEFT JOIN
     filetag ft
     ON f.imgId = ft.imgId
GROUP BY f.imgId;

Один комментарий: все круглые скобки и обратные пометки затрудняют написание и понимание запроса.

Производительность должна быть удовлетворительной индекс для filetab(imgId, tag).

С тем же индексом вы можете обнаружить, что коррелированный подзапрос работает быстрее:

SELECT f.imgId,
       (SELECT GROUP_CONCAT(ft.tag) 
        FROM filetag ft
        WHERE f.imgId = ft.imgId
       ) AS tags
FROM file f ;

Это позволяет избежать внешнего GROUP BY, что может быть производительностью выиграть.

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