Как получить сущности только с 1 связью many-to-many?

76
25 июня 2021, 06:30
    SELECT p0_.id                AS id
FROM product p0_
         LEFT JOIN product_color_group p7_ ON p0_.id = p7_.product_id
         LEFT JOIN color_group c3_ ON c3_.id = p7_.color_group_id
WHERE c3_.id IN (17, 15)
GROUP BY p0_.id
HAVING COUNT(DISTINCT c3_.id) = 1
ORDER BY p0_.id ASC
LIMIT 18;

В таблице product_color_group только product_id и color_group_id

Нужно показывать товары у которых есть только один из выбранных цветов (или 17 или 15). А запрос возвращает и товары, у которых есть например цвета 17 и 3 В чем проблема?

Answer 1

Попробуйте рассуждать немного более по-программистски. Надо выбрать из таблицы product_color_group (внезапно!) только те строки, которые имеют единственное на таблицу product_id (только один цвет). Кроме того, в расчёт берём строки только с color_group_id = 17 и 15.

Теперь осталось сджойнить это с product и color_group.

UPD таки просто

select
    any_value(`products`.`name`),
    any_value(`colors`.`name`),
    count(`product-colors`.`productId`) as `colorsCount`,
    any_value(`product-colors`.`colorId`) as `colorId`
from `product-colors`
inner join `products` on `products`.`id` = `product-colors`.`productId`
inner join `colors` on `colors`.`id` = `product-colors`.`colorId`
group by `product-colors`.`productId`
having
    `colorsCount` = 1
    and `colorId` in (2, 3)

Или вот с подзапросом (просто для красоты)

select
    `products`.*,
    `colors`.*
from (
    select
        `productId`,
        any_value(`colorId`) as `colorId`,
        count(`productId`) as `colorsCount`
    from `product-colors`
    group by `productId`
    having
        `colorsCount` = 1
        and `colorId` in (2, 3)
) as `product-colors`
inner join `products` on `products`.`id` = `product-colors`.`productId`
inner join `colors` on `colors`.`id` = `product-colors`.`colorId`
order by `products`.`id`
limit 18;

UUPD Подумал ещё. С небольшим лимитом, при большом количестве записей в таблице продуктов будет оптимальнее подзапрос в where.

select
    `products`.*,
    `colors`.*
from `products`
inner join `product-colors` on `product-colors`.`productId` = `products`.`id`
inner join `colors` on `colors`.`id` = `product-colors`.`colorId`
where (
    select count(*)
    from `product-colors`
    where `product-colors`.`productId` = `products`.`id`
) = 1
and `colors`.id in (2, 3)
order by `products`.`id`
limit 18;
READ ALSO
Как выбрать уникальные значение с привязкой по дате MySql?

Как выбрать уникальные значение с привязкой по дате MySql?

Не могу, выполнит выборкуБуду благодарен любой помощи

105
RedBean PHP Перемещение записи

RedBean PHP Перемещение записи

Пытаюсь переместить запись с одной таблицы в другую с удалениемСначала нахожу ее $info= R::findOne("books", "book_id= ?", array($_POST['id'])); Потом пытаюсь вставить...

119
Задача по рекурсии

Задача по рекурсии

Всем приветИзучаю PHP Столкнулся с интересной задачей, не могу решить ((

96