简体   繁体   English

如何将产品计数到按组分隔的多个过滤器中

[英]How to count products to multiple filters separated by group

I like to make counter for product filters like this one Online Shop , when you select any filter/option from GROUP X to count/update products into other GROUPS->filters/options but not in the current one我喜欢为这样一个在线商店的产品过滤器制作计数器,当您 select 组 X 中的任何过滤器/选项以将产品计数/更新到其他 GROUPS->过滤器/选项但不在当前组中时

for example if this is frontend filters checkboxes例如,如果这是前端过滤器复选框

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)

We are looking for result only from one category_id 127我们只从一个 category_id 127 中寻找结果

Example of same group check counting同组支票计数示例

If option_id: 52 checked如果 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)

Result:结果:

option_id:38    0,
option_id:49    2,
option_id:51    1,
option_id:52    21

option_id:51 and 52 still have initial state option_id:51 和 52 仍然有初始 state

If option_id: 51 checked如果 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)

Result:结果:

38  0
49  1
51  1
52  21

option_id:51 and 52 still have initial state option_id:51 和 52 仍然有初始 state

Example of different group check counting不同组检查计数的示例

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)

Result:结果:

38  0
49  2
51  1
52  2

all option should become updated and lose their initial state所有选项都应更新并丢失其初始 state

When you select one or more option_id from same group_id logic of showing products will be当您 select 时,来自相同 group_id 的一个或多个 option_id 显示产品的逻辑将是

for example: show products with size 10m and show products with 20m例如:展示尺寸为10m的产品,展示尺寸为20m的产品

if you select option_id:51 first it should not update option_id:52 becasue they are in same group but will update all option_id in group_id: 32 and so on如果你 select option_id:51 首先它不应该更新 option_id:52 因为它们在同一个组中,但会更新 group_id: 32 中的所有 option_id 等等

When you select option_id from different group_id logic of showing products will be当您 select option_id 来自不同 group_id 的显示产品逻辑时

for example: show products with size 10m who also have color green (if is available)例如:显示尺寸为 10m 且颜色为绿色的产品(如果有)

@Akina has done most of the code for counting in this Topic @Akina 完成了本主题中的大部分计数代码

Working example of DB and Query数据库和查询的工作示例

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);

(What is the "question"?) (什么是“问题”?)

I think the best way to implement such is to build a query based on the checkboxes, then process the data in a single pass in your application language.我认为实现这一点的最佳方法是基于复选框构建查询,然后在应用程序语言中一次性处理数据。

Side issue: Switch from MyISAM to InnoDB.附带问题:从 MyISAM 切换到 InnoDB。

Side issue: Shrink INT (which takes 4 bytes) to smaller datatypes.附带问题:将INT (占用 4 个字节)缩小为更小的数据类型。

The point behind these side issues is performance and space.这些附带问题背后的重点是性能和空间。 Many of the generated queries will involve a full table scan, filtering as it goes.许多生成的查询将涉及全表扫描,同时进行过滤。 (That is, INDEXes will not be useful much of the time.) (也就是说, INDEXes在很多时候都不会有用。)

The user can click multiple boxes in each grouping, correct?用户可以单击每个分组中的多个框,对吗? Then consider having, for example, TINYINT UNSIGNED , which has 8 bits (in 1 byte) to handle up all combinations of up to 8 choices.然后考虑使用例如TINYINT UNSIGNED ,它有 8 位(1 个字节)来处理最多 8 个选项的所有组合。 For example, instead of例如,而不是

AND size_id IN (0, 1)   -- 0 means '65in+'; 1 means '50-65in'

do

AND ((size_opts & 0x3) = 0x3)

That is, the bottom bit of size_opts represents '65in+', etc.size_opts的低位代表'65in+'等。

This would shrink the dataset quite a bit and require different pre-processing to generate the queries.这将大大缩小数据集,并需要不同的预处理来生成查询。

Note that the value of your size_id is 0..4, my size_opts would have some or all of the bottom 5 bits on.请注意,您的size_id的值为 0..4,我的size_opts将有部分或全部底部 5 位。

ORing together (1 << size_id) values gets you from size_id to size_opts . ORing 一起 (1 << size_id) 值可以让你从size_idsize_opts

(More) (更多的)

There are 2 things going on:有两件事发生:

  • Filtering (limiting the display by brand/price/color/whatever)过滤(按品牌/价格/颜色/其他限制显示)
  • Counting how many are still in the running (by each remaining criteria)计算有多少仍在运行中(按每个剩余标准)

To goals are needed to make it somewhat efficient:需要达到目标才能使其有点效率:

  • Shrink the dataset as much as possible尽可能缩小数据集
  • Don't include in the table any items that are 'deleted' etc. Don't include any columns that are not relevant to the filtering and counting.不要在表中包含任何“已删除”的项目等。不要包含任何与过滤和计数无关的列。 They fight with the shrinkage goal他们与收缩目标作斗争
  • Shrink the categorization as much as possible.尽可能缩小分类。 The "bit fiddling" I suggested may be optimal.我建议的“摆弄”可能是最佳选择。
  • Build the query dynamically.动态构建查询。 Leave out unnecessary tests.省去不必要的测试。 (Example: When nothing is clicked for Brand, don't test for Brand.) (例如:品牌没有点击时,不要测试品牌。)
  • To rephrase, build a table just for this purpose.换句话说,就是为此目的建立一个表。 Focus on it;专注于它; ignore all other aspects of the data.忽略数据的所有其他方面。 Even if the data in this table is redundant, you must optimize this table.即使这张表中的数据是多余的,你也必须优化这张表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM