doumi9618 2016-08-18 09:36
浏览 28
已采纳

如何在MySQL中查询产品和过滤器之间的多对多关系?

I have three tables viz. tb_filters, tb_products, and tb_products_to_filters. The structure of these tables along with some dummy data is given by:

tb_filters:

CREATE TABLE IF NOT EXISTS `tb_filters`
(
    `filter_id` INT (11) AUTO_INCREMENT PRIMARY KEY,
    `filter_name` VARCHAR (255)
);

INSERT INTO `tb_filters`
(`filter_name`)
VALUES ('USB'),
('High Speed'),
('Wireless'),
('Ethernet');

enter image description here

tb_products:

CREATE TABLE IF NOT EXISTS `tb_products`
(
    `product_id` INT (11) AUTO_INCREMENT PRIMARY KEY,
    `product_name` VARCHAR (255)
);

INSERT INTO `tb_products`
(`product_name`)
VALUES ('Ohm precision shunt resistor'),
('Orchestrator Libraries'),
('5cm scanner connection'),
('Channel isolated digital'),
('Network Interface Module');

enter image description here

tb_products_to_filters:

CREATE TABLE IF NOT EXISTS `tb_products_to_filters`
(
    `id` INT (11) AUTO_INCREMENT PRIMARY KEY,
    `product_id` INT (11),
    `filter_id` INT (11)
);

INSERT INTO `tb_products_to_filters`
(`product_id`, `filter_id`)
VALUES (1, 1),
(2, 2),
(3, 3),
(4, 3),
(1, 3);

enter image description here

By looking into above "tb_products_to_filters" table, my required queries are:

When filter id = 1 and 3 are selected via checkbox on the page, all those products which belong to filter id 1 as well as filter id 3 must be fetched from the database. In this case, the product with id 1 should come.

Second, when only one filter (say id = 3) is checked, then all those products which fall under this id should be fetched. In this condition, the products id 1, 3 and 4 will come.

If filter id 2 is selected, then only one product with id = 2 will come.

If combination of filter (2 and 3) is selected, then no product will come because there is no product which belongs to both of them.

What is the way of writing queries to obtain above goal?

Please note that I want to include columns: product_id, product_name, filter_id and filter_name to display data in table result set.

EDIT:

The output should match below when filter ids 1 and 3 were checked:

enter image description here

EDIT 2:

I'm trying below query to fetch results when filter 1 and 3 were checked:

SELECT `p`.`product_id`, `p`.`product_name`, 
GROUP_CONCAT(DISTINCT `f`.`filter_id` ORDER BY `f`.`filter_id` SEPARATOR ', ') AS filter_id, GROUP_CONCAT(DISTINCT `f`.`filter_name` ORDER BY `f`.`filter_name` SEPARATOR ', ') AS filter_name 
FROM `tb_products` AS `p` INNER JOIN `tb_products_to_filters` AS `ptf` 
ON `p`.`product_id` = `ptf`.`product_id` INNER JOIN `tb_filters` AS `f` 
ON `ptf`.`filter_id` = `f`.`filter_id` GROUP BY `p`.`product_id` 
HAVING GROUP_CONCAT(DISTINCT `ptf`.`filter_id` SEPARATOR ', ') = ('1,3') 
ORDER BY `p`.`product_id`

But unfortunately, it returns an empty set. Why?

  • 写回答

1条回答 默认 最新

  • dpkrh2444 2016-08-18 09:41
    关注

    You can use the HAVING clause with GROUP_CONCAT :

    SELECT t.product_id,tp.product_name,
           GROUP_CONCAT(t.filter_id) as filter_id,
           GROUP_CONCAT(tb.filter_name) as filter_name
    FROM tb_products_to_filters t
    INNER JOIN tb_filters tb ON(t.filter_id = tb.filter_id)
    INNER JOIN tb_products tp ON(t.product_id = tp.product_id)
    WHERE t.filter_id IN(1,3)
    GROUP BY t.product_id
    HAVING COUNT(distinct t.filter_id) = 2
    

    You can adjust this any way you want. Note that the number of arguments placed inside the IN() should be the same as the COUNT(..) = X

    EDIT:

    A DISTINCT keyword is required in GROUP_CONCAT while fetching those columns otherwise all the filters would come in the list. I tried it by doing

    SELECT t.product_id,tp.product_name,
           GROUP_CONCAT(DISTINCT t.filter_id ORDER BY `t`.`filter_id` SEPARATOR ', ') as filter_id,
           GROUP_CONCAT(DISTINCT tb.filter_name ORDER BY tb.filter_name SEPARATOR ', ') as filter_name
    FROM tb_products_to_filters t
    INNER JOIN tb_filters tb ON(t.filter_id = tb.filter_id)
    INNER JOIN tb_products tp ON(t.product_id = tp.product_id)
    WHERE t.filter_id IN(1,3)
    GROUP BY t.product_id
    HAVING COUNT(distinct t.filter_id) = 2
    

    But still all the filter names (Ethernet, High Speed, USB, Wireless) are coming in the list. How to list only those filter names whose corresponding filter id (1, 3) are in the string?

    enter image description here

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效