php - дважды проверять один и тот же столбец в запросе mysqli - PullRequest
1 голос
/ 24 марта 2020

У меня есть 3 таблицы в моей php системе.
Эти таблицы product, category, product_categories.

Продукт

pid | product_name | price
1 | Nike T-Shirt | 23

Категория

cid | category_name
1 | Men 
2 | Women

Product_categories

pcid | cid | pid
1 | 1 | 1 
2 | 2 | 1

Это означает, что 1 товар может быть в обеих категориях.
Сейчас я занимаюсь поиском товара раздел с фильтром.
Если пользователь выбирает обе категории, должны отображаться все продукты в выбранных категориях.

Пример. Если пользователь выбирает как мужчин, так и женщин, должна отображаться футболка Nike.

Используемый мной запрос:

select p.* 
from products p 
left join product_categories pc on pc.pid=p.pid 
WHERE pc.cid ='1' AND pc.cid = '2'

Но он не возвращает правильные продукты.

Где ошибка?

Ответы [ 2 ]

0 голосов
/ 25 марта 2020

Вот несколько альтернатив:

-- All products that are at lest in one of the desired categories
select * from product where product.pid = any (select product_category.pid from product_category where cid = 1 or cid = 2);
-- Products that are in both categories
select * from product where product.pid = any (
  select product_category.pid from product_category where cid = 1 or cid = 2 group by pid having count(cid) = 2
);
-- Products with additional information "in how many desired categories they are"
-- You can order by it and/or filter on it
with product_category_matches as (
  select pid, count(*) as category_count from product_category where cid in (1, 2) group by pid
)
select *, product_category_matches.category_count from 
product inner join product_category_matches on product.pid = product_category_matches.pid
where product_category_matches.category_count > 0 -- Product must be at least in one desired category
order by  product_category_matches.category_count desc
0 голосов
/ 24 марта 2020

Требуются условия, охватывающие несколько строк, что предполагает агрегирование. Вы можете объединить таблицы, group by product, и использовать для фильтрации предложение having:

select p.id, p.product_name, p.price
from product p
inner join product_category pc on pc.pid = p.pid
inner join category c on c.cid = pc.cid
where c.category_name in ('Men', 'Women')
group by p.pid, p.product_name, p.price
having max(c.category_name = 'Men') = 1 and max(c.category_name = 'Women') = 1

Если вы можете фильтровать по идентификатору категории, а не по имени категории, то вам нужно на одно объединение меньше:

select p.id, p.product_name, p.price
from product p
inner join product_category pc on pc.pid = p.pid
where pc.cid in (1, 2)
group by p.pid, p.product_name, p.price
having max(pc.cid= 1) = 1 and max(pc.cid = 2) = 1
...