我在 2020 年 1 月 10 日发布了一个类似的问题(见这里),但我的问题/问题从那时起就扩大了,不想让警察站在我的背上;)
这是标准:
- 有过滤器类别,并且有属于这些类别的过滤器。
- 每个过滤器都会显示属于某个过滤器的产品数量。
- 可用过滤器的数量需要根据活动过滤器的选择减少,不仅是那些仍然适用于产品池的过滤器,还有那些也与其他过滤器类别的子过滤器相关的过滤器。
- 上面有一个警告,如果只有一个过滤器类别选择了子过滤器,那么所有同级过滤器(相同过滤器类别的过滤器仍将显示)直到另一个过滤器类别的过滤器被激活。一旦选择了来自另一个过滤器类别/父级的过滤器,之前的完整列表可以减少,但之前选择的过滤器必须保持活动状态,如果是这种情况,则只显示零计数。
我认为我非常接近下面的 SQL,但它不会在选择时正确更新属于每个过滤器的产品数量。我可以让它工作的唯一方法是,如果我在下面的 SQL 中将 OR 更改为 AND,但这不会显示属于具有活动子过滤器的过滤器类别的其他子过滤器。
我在这里提供了架构和示例数据,以及相同的http://sqlfiddle.com/#!9/afbd4d7/1/0:
CREATE TABLE `store_categories` (
`categories_id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`categories_id`),
KEY `idx_categories_parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `store_products` (
`products_id` int(11) NOT NULL AUTO_INCREMENT,
`products_status` tinyint(1) NOT NULL,
PRIMARY KEY (`products_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `store_products_filters` (
`pf_id` int(11) NOT NULL AUTO_INCREMENT,
`pf_name` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
`pf_sort` int(4) DEFAULT '0',
`pf_to_pfc_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`pf_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `store_products_filters_categories` (
`pfc_id` int(11) NOT NULL AUTO_INCREMENT,
`pfc_name` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
`pfc_sort` int(4) DEFAULT '0',
PRIMARY KEY (`pfc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `store_products_filters_to_products` (
`pftp_id` int(11) NOT NULL AUTO_INCREMENT,
`pftp_pf_id` int(11) DEFAULT NULL,
`pftp_products_id` int(11) DEFAULT NULL,
PRIMARY KEY (`pftp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `store_products_to_categories` (
`products_id` int(11) NOT NULL,
`categories_id` int(11) NOT NULL,
PRIMARY KEY (`products_id`,`categories_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `store_categories` VALUES ('1', '0');
INSERT INTO `store_categories` VALUES ('2', '1');
INSERT INTO `store_categories` VALUES ('3', '0');
INSERT INTO `store_categories` VALUES ('4', '1');
INSERT INTO `store_categories` VALUES ('5', '0');
INSERT INTO `store_categories` VALUES ('6', '0');
INSERT INTO `store_products` VALUES ('1', '1');
INSERT INTO `store_products` VALUES ('2', '1');
INSERT INTO `store_products` VALUES ('3', '1');
INSERT INTO `store_products` VALUES ('4', '1');
INSERT INTO `store_products` VALUES ('5', '0');
INSERT INTO `store_products_filters` VALUES ('1', 'Small', '0', '1');
INSERT INTO `store_products_filters` VALUES ('2', 'Medium', '0', '1');
INSERT INTO `store_products_filters` VALUES ('3', 'Large', '0', '1');
INSERT INTO `store_products_filters` VALUES ('4', 'Extra Large', '0', '1');
INSERT INTO `store_products_filters` VALUES ('5', 'Circle', '0', '2');
INSERT INTO `store_products_filters` VALUES ('6', 'Square', '0', '2');
INSERT INTO `store_products_filters` VALUES ('7', 'Triangle', '0', '2');
INSERT INTO `store_products_filters` VALUES ('8', 'Red', '5000', '3');
INSERT INTO `store_products_filters` VALUES ('9', 'Blue', '5000', '3');
INSERT INTO `store_products_filters` VALUES ('10', 'Black', '2000', '3');
INSERT INTO `store_products_filters` VALUES ('11', 'Yellow', '5000', '3');
INSERT INTO `store_products_filters_categories` VALUES ('1', 'Size', '300');
INSERT INTO `store_products_filters_categories` VALUES ('2', 'Type', '100');
INSERT INTO `store_products_filters_categories` VALUES ('3', 'Colour', '400');
INSERT INTO `store_products_filters_to_products` VALUES ('1', '1', '1');
INSERT INTO `store_products_filters_to_products` VALUES ('2', '6', '1');
INSERT INTO `store_products_filters_to_products` VALUES ('3', '9', '1');
INSERT INTO `store_products_filters_to_products` VALUES ('4', '1', '2');
INSERT INTO `store_products_filters_to_products` VALUES ('5', '5', '2');
INSERT INTO `store_products_filters_to_products` VALUES ('6', '8', '2');
INSERT INTO `store_products_filters_to_products` VALUES ('7', '2', '3');
INSERT INTO `store_products_filters_to_products` VALUES ('8', '7', '3');
INSERT INTO `store_products_filters_to_products` VALUES ('9', '11', '3');
INSERT INTO `store_products_filters_to_products` VALUES ('10', '3', '4');
INSERT INTO `store_products_filters_to_products` VALUES ('11', '5', '4');
INSERT INTO `store_products_filters_to_products` VALUES ('12', '10', '4');
INSERT INTO `store_products_to_categories` VALUES ('1', '2');
INSERT INTO `store_products_to_categories` VALUES ('2', '2');
INSERT INTO `store_products_to_categories` VALUES ('3', '2');
INSERT INTO `store_products_to_categories` VALUES ('4', '2');
INSERT INTO `store_products_to_categories` VALUES ('5', '2');
有 3 个有源滤波器,Small、Medium 和 Circle。有 2 个“小”尺寸的产品 有 1 个“中”尺寸的产品 有 2 个应用了“圆形”过滤器的产品,但只有一个是“小”,另一个是“大”
应用了中小型过滤器后,我希望/喜欢 Circle 显示 1,但它显示的计数为 2
OR pf.pf_id IN (
SELECT
pf_id
FROM
store_products_filters
WHERE
pf_to_pfc_id IN (1, 2)
)
到目前为止,我的想法是如果来自多个过滤器类别的过滤器处于活动状态,则删除上述 SQL。
您可以在此站点https://www.ukpos.com/display-stands-frames-and-noticeboards上看到我正在尝试实现的示例,该站点由 Magento 提供支持。我不确定过滤器是开箱即用还是添加了插件。
下面是我的完整 SQL。
SELECT
pfc.pfc_id,
pfc.pfc_name,
pf.pf_id,
pf.pf_name,
count(pftp.pftp_pf_id) AS products_in_filter
FROM
store_products_filters_to_products pftp
LEFT JOIN store_products_filters pf ON pftp.pftp_pf_id = pf.pf_id
LEFT JOIN store_products_filters_categories pfc ON pf.pf_to_pfc_id = pfc_id
WHERE
pftp_products_id IN (
SELECT
ptc.products_id
FROM
store_products_to_categories ptc
LEFT JOIN store_products p ON ptc.products_id = p.products_id
WHERE
p.products_status = 1
AND (
ptc.categories_id = 1
OR ptc.categories_id IN (
SELECT
categories_id
FROM
store_categories
WHERE
parent_id = '1'
)
)
)
AND (
pf.pf_id IN (
SELECT
pftp_pf_id
FROM
store_products_filters_categories
WHERE
pftp_products_id IN (
SELECT
pftp.pftp_products_id
FROM
store_products_filters_to_products pftp
JOIN store_products_filters pf ON pf.pf_id = pftp.pftp_pf_id
GROUP BY
pftp.pftp_products_id
HAVING
(
sum(pf.pf_id = 1) > 0
OR sum(pf.pf_id = 2) > 0
)
AND (sum(pf.pf_id = 5) > 0)
)
)
OR pf.pf_id IN (
SELECT
pf_id
FROM
store_products_filters
WHERE
pf_to_pfc_id IN (1, 2)
)
)
GROUP BY
pfc.pfc_id,
pftp.pftp_pf_id
ORDER BY
pfc.pfc_sort ASC,
pfc.pfc_name ASC,
pf.pf_sort ASC,
pf.pf_name ASC