如何使用 MySQL 应用产品范围过滤器

How can I apply product range filters using MySQL

我正在努力为我的一个项目解决这个问题。我正在使用 codeigniter 3 和 MySQL 8。所以请专家帮助我。这是描述。

我有如下 2 个表:

产品:

| id | name      |
| -- | --------- |
| 1  | Product 1 |
| 2  | Product 2 |
| 3  | Product 3 |
| 4  | Product 4 |

产品过滤器:

| product_id | filter_id | value  |
| ---------- | --------- | ------ |
| 1          | 1         | 60     |
| 1          | 2         | 40     |
| 2          | 1         | 400    |
| 2          | 2         | 30     |
| 3          | 1         | 80     |
| 3          | 2         | 20     |
| 4          | 1         | 50     |
| 4          | 2         | 100    |

SQL供您参考:

CREATE TABLE IF NOT EXISTS `product` (
  `id` int(10) unsigned NOT NULL,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `product` (`id`, `name`) VALUES
  ('1', 'Product 1'),
  ('2', 'Product 2'),
  ('3', 'Product 3'),
  ('4', 'Product 4');
  
CREATE TABLE IF NOT EXISTS `product_filter` (
  `product_id` int(10) unsigned NOT NULL,
  `filter_id` int(10) unsigned NOT NULL,
  `value` int(10) unsigned NOT NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `product_filter` (`product_id`, `filter_id`, `value`) VALUES
  ('1', '1', '60'),
  ('1', '2', '40'),
  ('2', '1', '400'),
  ('2', '2', '30'),
  ('3', '1', '80'),
  ('3', '2', '20'),
  ('4', '1', '50'),
  ('4', '2', '100');

http://sqlfiddle.com/#!9/8c071f

对于一个产品,可以有多个过滤器,如上。但不能两次使用相同的过滤器。对于每个产品,每个过滤器都可以有一个值。

我想要以下场景:

例如,我有 10 个电源适配器。我想用电压和瓦特过滤掉它。因此,过滤器 1 将是电压,而 2 将是瓦特。现在我发送范围值以通过 0 - 200 伏和 0 - 50 瓦的消耗过滤特定产品。我的意思是这两个条件都应该适用。

结果应该是产品列表:

| id | name      |
| -- | --------- |
| 1  | Product 1 |
| 3  | Product 3 |

我使用多个 AND 尝试了以下 sql,它的 return 是一个空结果。这是我使用的示例查询。

SELECT p.*
FROM product p
JOIN product_filter fp ON fp.product_id = p.id
WHERE
(
   fp.filter_id = 1 AND fp.value >= 0 AND fp.value <= 200
) AND 
(
   fp.filter_id = 2 AND fp.value >= 0 AND fp.value <= 50
)

我怎样才能得到上面的答案?请帮忙。

考虑以下因素:

SELECT product_id
     , MAX(CASE WHEN filter_id = 1 THEN value END) v
     , MAX(CASE WHEN filter_id = 2 THEN value END) w
  FROM product_filter
 GROUP
    BY product_id;

+------------+------+------+
| product_id | v    | w    |
+------------+------+------+
|          1 |   60 |   40 |
|          2 |  400 |   30 |
|          3 |   80 |   20 |
|          4 |   50 |  100 |
+------------+------+------+

因此,为了我们的目的,这可以重新排列为...

SELECT product_id
  FROM product_filter
 GROUP
    BY product_id
HAVING MAX(CASE WHEN filter_id = 1 THEN value END) BETWEEN 0 AND 200
   AND MAX(CASE WHEN filter_id = 2 THEN value END) BETWEEN 0 AND 50
   ;

+------------+
| product_id |
+------------+
|          1 |
|          3 |
+------------+

请注意,这不太可能比您多次加入 table 的想法更有效,但它更易于阅读。