我有一个product_table
,其中包含product_id
个字段。
我正在创建一个包含2个字段tag_table
和tag_id
的{{1}}。
标签可以是“银”或“宾州”等等。
我还使用tag_name
和product_tag_map
创建product_id
表格,以便将产品映射到任意数量的代码。
如果我想创建一个包含所有标记为“silver”,“necklace”,“diamond”的产品的类别。但也排除任何标记为“初始”,“旅程”的产品
(显然我会使用tag_id而不是tag_name,所以带有标签[2,4,5]的产品没有标签[3,6])
如何创建临时产品表并使用匹配的产品填充它?
这是我的product_tag_map表:
tag_id
注意:我没有使用CREATE TABLE `product_tag_map` (
`product_tag_map_id` int(11) NOT NULL auto_increment,
`tag_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
PRIMARY KEY (`product_tag_map_id`),
UNIQUE KEY `tag_id` (`tag_id`,`product_id`),
KEY `tag_id_2` (`tag_id`)
) ENGINE=MyISAM AUTO_INCREMENT=7897 DEFAULT CHARSET=utf8
。我只是习惯于为每张桌子提供一个主键。所以如果我应该把它删除那么好。
答案 0 :(得分:1)
问题是,你需要一个临时表 ?为什么不直接查询呢?
SELECT
p.product_id,
p.product_name
FROM
product_table p
WHERE
EXISTS (
SELECT 1
FROM product_tag_map
WHERE product_id = p.product_id AND tag_id IN (2,4,5)
)
AND NOT EXISTS (
SELECT 1
FROM product_tag_map
WHERE product_id = p.product_id AND tag_id IN (3,6)
)
创建适当的索引(一个多列索引超过(product_tag_map.product_id, product_tag_map.tag_id)
,另一个超过(product_tag_map.tag_id)
,除了“普通”PK / FK索引之外),这应该足够快。
编辑:可缓存(就查询计划而言)以及上述更具动态的变体:
创建一个user_searches
表(search_session_id, tag_id, include)
,其中多列索引超过(search_session_id, include)
,另一个索引超过tag_id
。然后在用户选择条件时填写它:
search_session_id tag_id include
...
4711 2 1
4711 4 1
4711 5 1
4711 3 0
4711 6 0
...
并且像这样查询:
SELECT
p.product_id,
p.product_name
FROM
product_table p
WHERE
EXISTS (
SELECT 1
FROM product_tag_map m INNER JOIN user_searches s ON s.tag_id = m.tag_id
WHERE m.product_id = p.product_id
AND s.search_session_id = 4711 /* this should be a parameter */
AND s.include = 1
)
AND NOT EXISTS (
SELECT 1
FROM product_tag_map m INNER JOIN user_searches s ON s.tag_id = m.tag_id
WHERE m.product_id = p.product_id
AND s.search_session_id = 4711 /* this should be a parameter */
AND s.include = 0
)
答案 1 :(得分:1)
您可以在select语句上创建视图。
(视图基本上是一个虚拟表,您可以轻松查询,但是可以使用复杂语句中的数据进行查询。阅读本手册,在性能和读/写行为方面并非如此简单。)
但是您的查询可能如下所示:
SELECT
product_id, count(*) as total
FROM tag_map WHERE tag_id IN (2,4,5)
AND total = 3
AND product_id NOT IN (
SELECT product_id, count(*) as total FROM tag_map WHERE tag_id IN (3,6)
WHERE total = 2 GROUP BY ( product_id )
)
GROUP BY ( product_id )
你也可以加入,但我认为它会慢一些。