Один ко многим, показать все отношения, включая недостающие отношения - PullRequest
0 голосов
/ 04 августа 2020

У меня есть 3 таблицы: 1 для tags, 1 для languages и 1 для translations.

Таблица translations имеет столбцы идентификаторов внешних ключей, которые указывают как на tags и languages таблица.

В translations table 1 тег может быть связан с несколькими языками, он имеет следующую структуру:

id | tag | language | translation
1    1     1          "hello"
2    1     2          "olá"
3    1     3          "bonjour"
4    2     1          "world"
5    3     1          "dog"

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

В примере не более 3 языков, теги 2 и 3 связаны только с одним языком.

Я использую MySQL.

Вот код для таблиц:

CREATE TABLE `tags` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `tag` VARCHAR(100) NOT NULL DEFAULT '' COLLATE 'ascii_bin',
    `isActive` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
    `createdAt` DATETIME NOT NULL DEFAULT current_timestamp(),
    `updatedAt` DATETIME NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE INDEX `tag` (`tag`) USING BTREE
)
COLLATE='ascii_bin'
ENGINE=InnoDB
AUTO_INCREMENT=15
;

CREATE TABLE `languages` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `language` VARCHAR(5) NOT NULL DEFAULT '' COLLATE 'ascii_bin',
    `tag` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
    `name` VARCHAR(50) NOT NULL DEFAULT '0' COLLATE 'ascii_bin',
    `nativeName` VARCHAR(50) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_520_ci',
    `isActive` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
    `createdAt` DATETIME NOT NULL DEFAULT current_timestamp(),
    `updatedAt` DATETIME NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE INDEX `code` (`language`) USING BTREE,
    UNIQUE INDEX `name` (`name`) USING BTREE,
    UNIQUE INDEX `tag` (`tag`) USING BTREE,
    CONSTRAINT `FK_languages_tags` FOREIGN KEY (`tag`) REFERENCES `hello`.`tags` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
)
COLLATE='utf8mb4_unicode_520_ci'
ENGINE=InnoDB
AUTO_INCREMENT=9
;

CREATE TABLE `translations` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `tag` BIGINT(20) UNSIGNED NOT NULL DEFAULT '1',
    `language` BIGINT(20) UNSIGNED NOT NULL DEFAULT '1',
    `translation` VARCHAR(5000) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_520_ci',
    `createdAt` DATETIME NOT NULL DEFAULT current_timestamp(),
    `updatedAt` DATETIME NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
    PRIMARY KEY (`id`) USING BTREE,
    INDEX `FK_translations_tags` (`tag`) USING BTREE,
    INDEX `FK_translations_languages` (`language`) USING BTREE,
    CONSTRAINT `FK_translations_languages` FOREIGN KEY (`language`) REFERENCES `hello`.`languages` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT,
    CONSTRAINT `FK_translations_tags` FOREIGN KEY (`tag`) REFERENCES `hello`.`tags` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
)
COLLATE='utf8mb4_unicode_520_ci'
ENGINE=InnoDB
AUTO_INCREMENT=72
;

Вот что у меня есть:

SELECT
`translations`.`tag` AS `tagId`,
`tags`.`tag`,
`tags`.`isActive` AS `tagIsActive`,
`translations`.`language` AS `languageId`,
`languages`.`language`,
`languages`.`tag` AS `languageTagId`,
--
(SELECT `tag` FROM `tags` WHERE `id` = `languages`.`tag`) AS `languageTag`,
--
`languages`.`nativeName` AS `languageNativeName`,
`languages`.`isActive` AS `languageIsActive`,
`translations`.`id` AS `translationId`,
`translations`.`translation`
FROM `translations`
--
LEFT OUTER JOIN `tags`
ON `tags`.`id` = `translations`.`tag`
--
LEFT OUTER JOIN `languages`
ON `languages`.`id` = `translations`.`language`
--
ORDER BY `tags`.`tag` ASC,
`languages`.`language` ASC;

Как я уже сказал, если тег не соответствует all языкам, мне нужен как минимум перевод отображаться как null или как пустая строка.

1 Ответ

2 голосов
/ 04 августа 2020
SELECT *
FROM tags
CROSS JOIN languages
LEFT JOIN translations ON translations.tag = tags.id
                      AND translations.language = languages.id

скрипка

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