Избегайте повторных идентификаторов в сводном отношении - PullRequest
1 голос
/ 30 апреля 2020

У меня работает MySQL v.5.7.

Мне нужно выбрать продукты с уникальными (разными?) Рекламодателями в отношениях «многие ко многим».

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

Вот мой пример схемы:

Продукты

CREATE TABLE `products` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `products` (`id`, `name`)
VALUES
    (1, 'Product 1'),
    (2, 'Product 2'),
    (3, 'Product 3'),
    (4, 'Product 4'),
    (5, 'Product 5'),
    (6, 'Product 6');

Рекламодатели

CREATE TABLE `advertisers` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `advertisers` (`id`, `name`)
VALUES
    (1, 'Advertiser 1'),
    (2, 'Advertiser 2'),
    (3, 'Advertiser 3'),
    (4, 'Advertiser 4'),
    (5, 'Advertiser 5'),
    (6, 'Advertiser 6');

Pivot

CREATE TABLE `product_advertisers` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `product_id` int(11) unsigned NOT NULL,
  `advertiser_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `product_id` (`product_id`),
  KEY `advertiser_id` (`advertiser_id`),
  CONSTRAINT `product_advertisers_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `product_advertisers_ibfk_2` FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `product_advertisers` (`id`, `product_id`, `advertiser_id`)
VALUES
    (1, 1, 2),
    (2, 1, 5),
    (3, 2, 1),
    (4, 2, 5),
    (5, 3, 2),
    (6, 4, 1),
    (7, 4, 4),
    (8, 4, 6),
    (9, 5, 3),
    (10, 6, 6),
    (11, 6, 2);

Вот запрос, с которого я начинаю:

SELECT 
    `products`.`id`,
    `products`.`name`,
    GROUP_CONCAT(`advertisers`.`id`)
FROM
    `products`
        LEFT JOIN `product_advertisers` ON `product_advertisers`.`product_id` = `products`.`id`
        LEFT JOIN `advertisers` ON `advertisers`.`id` = `product_advertisers`.`advertiser_id`
GROUP BY
    `products`.`id`
;

DB Fiddle

Результаты

Мои наблюдения отмечены вручную в последнем столбце.

| id  | name      | GROUP_CONCAT(`advertisers`.`id`) | Observations
| --- | --------- | -------------------------------- |--------------
| 1   | Product 1 | 2,5                              | 
| 2   | Product 2 | 5,1                              | NOPE! ID 5 appears in Product 1
| 3   | Product 3 | 2                                | NOPE! ID 2 appears in Product 1
| 4   | Product 4 | 1,6,4                            | OK - No conflicts with Product 1
| 5   | Product 5 | 3                                | OK - No conflicts with Products 1 or 4
| 6   | Product 6 | 2,6                              | NOPE! ID 2 appears in Product 1, ID 6 appears in Product 4

Желаемые результаты

| id  | name      | GROUP_CONCAT(`advertisers`.`id`) |
| --- | --------- | -------------------------------- |
| 1   | Product 1 | 2,5                              |
| 4   | Product 4 | 1,6,4                            |
| 5   | Product 5 | 3                                |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...