[英]How to count products to multiple filters separated by group
我喜欢为这样一个在线商店的产品过滤器制作计数器,当您 select 组 X 中的任何过滤器/选项以将产品计数/更新到其他 GROUPS->过滤器/选项但不在当前组中时
例如,如果这是前端过滤器复选框
Size (group_id: 33)
10m (option_id: 52) (21 products)
20m (option_id: 51) (1 product)
Color (group_id: 32)
Green (option_id: 49) (22 products)
Black (option_id: 38) (1 product)
我们只从一个 category_id 127 中寻找结果
同组支票计数示例
如果 option_id: 52 选中
Size (group_id: 33)
[x] 10m (option_id: 52) (21 products)
20m (option_id: 51) (1 product)
Color (group_id: 32)
Green (option_id: 49) (22 products)
Black (option_id: 38) (1 product)
结果:
option_id:38 0,
option_id:49 2,
option_id:51 1,
option_id:52 21
option_id:51 和 52 仍然有初始 state
如果 option_id: 51 选中
Size (group_id: 33)
10m (option_id: 52) (21 products)
[x] 20m (option_id: 51) (1 product)
Color (group_id: 32)
Green (option_id: 49) (22 products)
Black (option_id: 38) (1 product)
结果:
38 0
49 1
51 1
52 21
option_id:51 和 52 仍然有初始 state
不同组检查计数的示例
Size (group_id: 33)
[x] 10m (option_id: 52) (21 products)
20m (option_id: 51) (1 product)
Color (group_id: 32)
[x] Green (option_id: 49) (22 products)
Black (option_id: 38) (1 product)
结果:
38 0
49 2
51 1
52 2
所有选项都应更新并丢失其初始 state
当您 select 时,来自相同 group_id 的一个或多个 option_id 显示产品的逻辑将是
例如:展示尺寸为10m的产品,展示尺寸为20m的产品
如果你 select option_id:51 首先它不应该更新 option_id:52 因为它们在同一个组中,但会更新 group_id: 32 中的所有 option_id 等等
当您 select option_id 来自不同 group_id 的显示产品逻辑时
例如:显示尺寸为 10m 且颜色为绿色的产品(如果有)
@Akina 完成了本主题中的大部分计数代码
SELECT options.option_id,
COUNT(DISTINCT CASE WHEN filter_counter.option_id = options.option_id
THEN product_id
END) option_count
FROM filter_counter
CROSS JOIN ( SELECT DISTINCT option_id
FROM filter_counter ) options
JOIN ( SELECT DISTINCT product_id
FROM filter_counter
WHERE option_id IN (51) ) filter1 USING (product_id)
GROUP BY options.option_id;
CREATE TABLE `filter_counter` (
`id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`option_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`manufacturer_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `filter_counter` (`id`, `group_id`, `option_id`, `product_id`, `category_id`, `manufacturer_id`) VALUES
(1, 33, 52, 5124, 65, 36),
(2, 33, 52, 5124, 127, 36),
(3, 33, 52, 5125, 65, 36),
(4, 33, 52, 5125, 127, 36),
(5, 33, 52, 5138, 65, 36),
(6, 33, 52, 5138, 127, 36),
(7, 33, 52, 5141, 65, 36),
(8, 33, 52, 5141, 127, 36),
(9, 33, 52, 5146, 65, 36),
(10, 33, 52, 5146, 127, 36),
(11, 33, 52, 5147, 65, 36),
(12, 33, 52, 5147, 127, 36),
(13, 33, 52, 5148, 65, 36),
(14, 33, 52, 5148, 127, 36),
(15, 33, 52, 5149, 65, 36),
(16, 33, 52, 5149, 127, 36),
(17, 33, 52, 5150, 65, 36),
(18, 33, 52, 5150, 127, 36),
(19, 33, 52, 5151, 65, 36),
(20, 33, 52, 5151, 127, 36),
(21, 33, 52, 5152, 65, 36),
(22, 33, 52, 5152, 127, 36),
(23, 33, 52, 5153, 65, 36),
(24, 33, 52, 5153, 127, 36),
(25, 33, 52, 5154, 65, 36),
(26, 33, 52, 5154, 127, 36),
(27, 33, 52, 5155, 65, 36),
(28, 33, 52, 5155, 127, 36),
(29, 33, 52, 5156, 65, 36),
(30, 33, 52, 5156, 127, 36),
(31, 33, 52, 5157, 65, 36),
(32, 33, 52, 5157, 127, 36),
(33, 33, 52, 7042, 65, 38),
(34, 33, 52, 7042, 127, 38),
(35, 33, 52, 7048, 65, 38),
(36, 33, 52, 7048, 127, 38),
(37, 33, 52, 7124, 65, 0),
(38, 33, 52, 7124, 127, 0),
(39, 32, 49, 7185, 65, 0),
(40, 32, 49, 7185, 127, 0),
(41, 32, 49, 7517, 65, 39),
(42, 32, 49, 7517, 127, 39),
(43, 32, 49, 7518, 65, 39),
(44, 32, 49, 7518, 127, 39),
(45, 32, 49, 7538, 65, 39),
(46, 32, 49, 7538, 127, 39),
(47, 32, 49, 7657, 65, 39),
(48, 32, 49, 7657, 127, 39),
(49, 32, 49, 7658, 65, 39),
(50, 32, 49, 7658, 127, 39),
(51, 32, 49, 7797, 65, 21),
(52, 32, 49, 7797, 127, 21),
(53, 32, 49, 7798, 65, 21),
(54, 32, 49, 7798, 127, 21),
(55, 32, 49, 7799, 65, 21),
(56, 32, 49, 7799, 127, 21),
(57, 32, 49, 7800, 65, 21),
(58, 32, 49, 7800, 127, 21),
(59, 32, 49, 7801, 65, 21),
(60, 32, 49, 7801, 127, 21),
(61, 32, 49, 7802, 65, 21),
(62, 32, 49, 7802, 127, 21),
(63, 32, 49, 7803, 65, 21),
(64, 32, 49, 7803, 127, 21),
(65, 32, 49, 7804, 65, 21),
(66, 32, 49, 7804, 127, 21),
(67, 32, 49, 7805, 65, 21),
(68, 32, 49, 7805, 127, 21),
(69, 32, 49, 7806, 65, 21),
(70, 32, 49, 7806, 127, 21),
(71, 32, 49, 7807, 65, 21),
(72, 32, 49, 7807, 127, 21),
(73, 32, 49, 7808, 65, 21),
(74, 32, 49, 7808, 127, 21),
(75, 32, 49, 7809, 65, 21),
(76, 32, 49, 7809, 127, 21),
(77, 32, 49, 7810, 65, 21),
(78, 32, 49, 7810, 127, 21),
(79, 32, 38, 7811, 65, 21),
(80, 32, 38, 7811, 127, 21),
(81, 32, 49, 8020, 65, 21),
(82, 32, 49, 8020, 127, 21),
(83, 33, 52, 8020, 65, 21),
(84, 33, 52, 8020, 127, 21),
(85, 32, 49, 8021, 65, 21),
(86, 32, 49, 8021, 127, 21),
(87, 33, 51, 8021, 65, 21),
(88, 33, 51, 8021, 127, 21),
(89, 33, 52, 8021, 65, 21),
(90, 33, 52, 8021, 127, 21);
(什么是“问题”?)
我认为实现这一点的最佳方法是基于复选框构建查询,然后在应用程序语言中一次性处理数据。
附带问题:从 MyISAM 切换到 InnoDB。
附带问题:将INT
(占用 4 个字节)缩小为更小的数据类型。
这些附带问题背后的重点是性能和空间。 许多生成的查询将涉及全表扫描,同时进行过滤。 (也就是说, INDEXes
在很多时候都不会有用。)
用户可以单击每个分组中的多个框,对吗? 然后考虑使用例如TINYINT UNSIGNED
,它有 8 位(1 个字节)来处理最多 8 个选项的所有组合。 例如,而不是
AND size_id IN (0, 1) -- 0 means '65in+'; 1 means '50-65in'
做
AND ((size_opts & 0x3) = 0x3)
即size_opts
的低位代表'65in+'等。
这将大大缩小数据集,并需要不同的预处理来生成查询。
请注意,您的size_id
的值为 0..4,我的size_opts
将有部分或全部底部 5 位。
ORing 一起 (1 << size_id) 值可以让你从size_id
到size_opts
。
(更多的)
有两件事发生:
需要达到目标才能使其有点效率:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.