我有三张桌子。 tb_filters,tb_products和tb_products_to_filters。这些表的结构以及一些虚拟数据由下式给出:
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');
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');
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);
通过查看上面的“tb_products_to_filters”表,我所需的查询是:
当通过页面上的复选框选择过滤器id = 1和3时,必须从数据库中提取属于过滤器ID 1和过滤器ID 3的所有产品。在这种情况下,应该出现id为1的产品。
其次,当只检查一个过滤器(比如id = 3)时,应该获取属于该id的所有产品。在这种情况下,产品ID 1,3和4将会出现。
如果选择了过滤器ID 2,则只有一个id = 2的产品将会到来。
如果选择过滤器(2和3)的组合,则不会有产品进入,因为没有产品属于它们。
编写查询以获得上述目标的方式是什么?
请注意,我想要包含列:product_id,product_name,filter_id和filter_name以显示表结果集中的数据。
修改
当检查过滤器ID 1和3时,输出应匹配如下:
编辑2:
我正在尝试下面的查询,以便在检查过滤器1和3时获取结果:
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`
但不幸的是,它返回一个空集。为什么呢?
答案 0 :(得分:2)
您可以将HAVING
子句与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
您可以按照自己的方式进行调整。请注意,IN()
内的参数数量应与COUNT(..) = X
修改强>
在获取这些列时,GROUP_CONCAT中需要DISTINCT关键字,否则所有过滤器都会出现在列表中。我试着做了
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
但仍然所有过滤器名称(以太网,高速,USB,无线)都在列表中。如何仅列出那些对应的过滤器id(1,3)在字符串中的过滤器名称?