SQL — Получение строк с одним результатом и выбранной опцией — Таблица отношений

#mysql #sql #postgresql

#mysql #sql #postgresql

Вопрос:

У меня есть таблица, в которой указаны отношения продуктов и цветов. Каждый продукт имеет один или несколько цветов. Возможно ли выполнить запрос, который возвращает только те продукты, которые имеют только один цвет и желаемый цвет?

Значение из api: color_slug = белый ;

Пример таблицы :

 color_table
 ---------- ------------ 
| color_id | color_slug |
 ---------- ------------ 
|        1 | white      |
|        2 | blue       |
|        3 | black      |
|        4 | green      |
|        5 | red        |
|        6 | yellow     |
 ---------- ------------ 
  
 product_table
 ------------ -------------- 
| product_id | product_name |
 ------------ -------------- 
|          1 | shoes        |
|          2 | shorts       |
|          3 | t-shirt      |
|          4 | jacket       |
|          5 | watch        |
|          6 | glasses      |
 ------------ -------------- 
  
 pc_relation
 ---- ------------ ---------- 
| id | product_id | color_id |
 ---- ------------ ---------- 
|  1 |          1 |        5 |
|  2 |          1 |        1 |
|  3 |          2 |        1 |
|  4 |          2 |        4 |
|  5 |          2 |        3 |
|  6 |          3 |        2 |
|  7 |          4 |        1 |
|  8 |          5 |        5 |
|  9 |          5 |        6 |
| 10 |          6 |        1 |
 ---- ------------ ---------- 
  

Выберите уникальные значения цвета (если я укажу, ГДЕ color_id = 1, цвета продукта не будут длиннее только одного цвета) :

 SELECT product_id 
FROM pc_relation
// WHERE color_id = 1
GROUP BY product_id 
HAVING MIN(color_id) = MAX(color_id)

  

pc_relation.id = 6,7,10

 SELECT *
FROM color_table
INNER JOIN pc_relation ON pc_relation.color_id = color_table.color_id 
INNER JOIN product_table ON pc_relation.product_id  = product_table.product_id
WHERE colors.color_slug = 'white'
  

Требуемые значения (color_slug = белый):

pc_relation.id = 7,10
product_table.product_name = jacket, glasses

* все комбинации уникальны и проиндексированы. Например, у меня не может быть одного продукта с одним и тем же цветом дважды.

Комментарии:

1. это mysql или postgresql?

Ответ №1:

Вы на правильном пути с вашим первым запросом. Переместите сравнение цветов в HAVING предложение:

 SELECT product_id 
FROM pc_relation
GROUP BY product_id 
HAVING MIN(color_id) = MAX(color_id) AND
       MIN(color_id) = 1;
  

Вы также можете сформулировать это с помощью NOT EXISTS :

 select r.*
from pc_relation r
where r.color_id = 1 and
      not exists (select 1
                  from pc_relation r2
                  where r2.product_id = r.product_id and r2.color_id <> r.color_id
                 );
  

Однако GROUP BY метод является более общим.

Комментарии:

1. Уже сделал это, но без MIN на MIN(color_id) = 1; Я попробую это сейчас.

2. Почему значение MIN имеет значение? Это сработало: MIN(color_table.color_slug) = ‘white’

3. @bmpf_pt . , , я не совсем понимаю вопрос. Вам нужна функция агрегирования в having предложении.