@Origihor

Множественные объединения c условием?

49eb2398d4c14493ad2e32d5913b04f5.png
SELECT 
  t1.id,
  t1.name AS product,
  t3.name AS color,
  t5.name AS size
FROM
  `product` AS t1
JOIN
  `product_color` AS t2 ON t1.id = t2.product_id
JOIN
  `color` AS t3 ON t2.color_id = t3.id
JOIN 
  `product_size` AS t4 ON t1.id = t4.product_id
JOIN 
  `size` AS t5 ON t4.size_id = t5.id

d8e4db16f006464795613d26771f371b.JPG
Вопрос:
Как получить список товаров удовлетворяющий сразу всем перечисленным ниже условиям?
  • черный цвет и размер S
  • черный цвет и размер M
  • размер L

Псевдокод:
WHERE
 (color = "black" and size = "S")
and
 (color = "black" and size = "M")
and
 (size = "L")

Обратите внимание, свойства "цвет" и "размер" - это поля разных таблиц.
В таблице всего два товара и всем перечисленным условиям удовлетворяет "jacket A".

В реальности, есть множество сущностей узкоспециализированной направленности, свойства этих сущностей хранятся с помощью N:M. Некоторые из этих свойств допускают вложенности, в результате чего, обычный select превращается в строку солидной длинны, не говоря уже о запросе с условием. Может я упустил что, ткните пальцем если не сложно.
  • Вопрос задан
  • 1999 просмотров
Решения вопроса 3
@Joysi75
По моему все можно :-) ибо
Я бы делал через subquery (удобно для выборок по разным условиям из составленного "набора" пересечений)
select BSproduct from
  ( -- Список продуктов имеющих черный цвет и малый размер
    select product as BSProduct from
      (
        SELECT  t1.id,  t1.name AS product,  t3.name AS color,  t5.name AS size
          FROM  `product` AS t1
          JOIN `product_color` AS t2 ON t1.id = t2.product_id
          JOIN `color` AS t3 ON t2.color_id = t3.id
          JOIN `product_size` AS t4 ON t1.id = t4.product_id
          JOIN `size` AS t5 ON t4.size_id = t5.id
      ) 
    where color = "black" and size = "S"  
  ) as BlackAndSmallSize, 
  ( -- Список продуктов имеющих черный цвет и средний размер
    select product as BMProduct from
      (
        SELECT  t1.id,  t1.name AS product,  t3.name AS color,  t5.name AS size
          FROM  `product` AS t1
          JOIN `product_color` AS t2 ON t1.id = t2.product_id
          JOIN `color` AS t3 ON t2.color_id = t3.id
          JOIN `product_size` AS t4 ON t1.id = t4.product_id
          JOIN `size` AS t5 ON t4.size_id = t5.id
      ) 
    where color = "black" and size = "M"  
  ) as BlackAndMidSize, 
  ( -- Список продуктов имеющих большой размер
    select product as LProduct from
      (
        SELECT  t1.id,  t1.name AS product,  t3.name AS color,  t5.name AS size
          FROM  `product` AS t1
          JOIN `product_color` AS t2 ON t1.id = t2.product_id
          JOIN `color` AS t3 ON t2.color_id = t3.id
          JOIN `product_size` AS t4 ON t1.id = t4.product_id
          JOIN `size` AS t5 ON t4.size_id = t5.id
      ) 
    where size = "L"  
  ) as LargeSize
where BSProduct=BMProduct and BMProduct=LProduct


Не знаю как насчет MySQL и его форков, в некоторых SQL серверах можно заранее задавать подзапросы типа
(
        SELECT  t1.id,  t1.name AS product,  t3.name AS color,  t5.name AS size
          FROM  `product` AS t1
          JOIN `product_color` AS t2 ON t1.id = t2.product_id
          JOIN `color` AS t3 ON t2.color_id = t3.id
          JOIN `product_size` AS t4 ON t1.id = t4.product_id
          JOIN `size` AS t5 ON t4.size_id = t5.id
      )

с помощью команды WITH - тогда объем текста выборки сократится в разы.
Ответ написан
@nozzy
Symfony, Laravel, SQL
select 
t1.*,
t3.name 
from 
product t1
inner join (
	select 
	product_id
	from product_size
	inner join size on id = size_id
	where name in ('S', 'M', 'L')
	group by product_id
	having count(product_id) = 3
) t2 on t2.product_id = t1.id
inner join (
	select 
	product_id 
	,name
	from product_color
	inner join color on id = color_id
	where name = 'black'
) t3 on t3.product_id = t2.product_id
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
У вас цвет и размер - независимые атрибуты товара, поэтому получается, что в каждом из имеющихся цветов товар есть в каждом из имеющихся размеров. Таким образом, точно по вашему условию составить запрос невозможно, из (чёрный S & чёрный M & любой L) оно вырождается в (чёрный & S & M & L).
SELECT `p`.`id` 
    FROM `product` AS `p`
    JOIN `product_color` AS `pc1` ON `pc1`.`product_id` = `p`.`id`
    JOIN `color` AS `c1` ON `c1`.`id` = `pc1`.`color_id` 
        AND `c1`.`name` = 'black'
    JOIN `product_size` AS `ps1` ON `ps1`.`product_id` = `p`.`id`
    JOIN `size` AS `s1` ON `s1`.`id` = `ps1`.`size_is` 
        AND `s1`.`name` = 'S'
    JOIN `product_size` AS `ps2` ON `ps2`.`product_id` = `p`.`id`
    JOIN `size` AS `s2` ON `s2`.`id` = `ps2`.`size_is` 
        AND `s2`.`name` = 'M'
    JOIN `product_size` AS `ps3` ON `ps3`.`product_id` = `p`.`id`
    JOIN `size` AS `s3` ON `s3`.`id` = `ps3`.`size_is` 
        AND `s3`.`name` = 'L'
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
mahoho
@mahoho
Full stack certified PHP developer.
так и пишите, как вы сказали:
WHERE
 (t3.name = 'black' and t5.name = 'S')
and
 (t3.name = 'black' and t5.name = 'M')
and
 (t5.name = 'L')

WHERE фильтрует уже результаты джоина и там все эти поля будут. Не забывайте, что алиасы использовать в WHERE нельзя - он исполнятся до SELECT, где эти алиасы определяются
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы