Php 如何从标记创建临时表?
我有一个Php 如何从标记创建临时表?,php,mysql,sql,Php,Mysql,Sql,我有一个product\u表,其中有一个product\u id 我正在创建一个带有两个字段的tag\u表,tag\u id和tag\u name 标签可以是“银色”或“宾夕法尼亚州立大学”等任何东西 我还创建了一个带有product\u id和tag\u id的product\u-tag\u-map表,以便将产品映射到任意数量的标签 如果我想创建一个包含所有标记为“银”、“项链”、“钻石”的产品的类别。但也不包括任何标记为“初始”、“旅程”的产品 (显然,我会使用tag_id而不是tag_na
product\u表
,其中有一个product\u id
我正在创建一个带有两个字段的tag\u表
,tag\u id
和tag\u name
标签可以是“银色”或“宾夕法尼亚州立大学”等任何东西
我还创建了一个带有product\u id
和tag\u id
的product\u-tag\u-map
表,以便将产品映射到任意数量的标签
如果我想创建一个包含所有标记为“银”、“项链”、“钻石”的产品的类别。但也不包括任何标记为“初始”、“旅程”的产品
(显然,我会使用tag_id而不是tag_name,因此带有标签[2,4,5]的产品没有标签[3,6])
如何创建临时产品表并用匹配的产品填充它
更新
这是我的产品标签地图表:
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
注意:我没有使用
product\u tag\u map\u id
进行任何操作。我只是习惯于这样给每个表一个主键。因此,如果我删除它,这很好。问题是,您需要临时表做什么?为什么不直接查询呢
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)
)
创建适当的索引(除了“正常”PK/FK索引外,在(product\u tag\u map.product\u id,product\u tag\u map.tag\u id)上创建一个多列索引,在(product\u tag\u map.tag\u id)
上创建一个单独的索引),这应该非常快
编辑:一个可缓存(就查询计划而言)且更具动态性的变量是:
创建一个user\u search
表(search\u session\u id,tag\u id,include)
,在(search\u session\u id,include)
上有一个多列索引,在tag\u 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
)
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 )
可以在select语句上创建视图
(视图基本上是一个虚拟表,您可以轻松查询,但它是使用复杂语句中的数据进行上传的。请阅读手册,它在性能和读/写行为方面并不是那么简单。)
但是,您的查询可能如下所示:
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
)
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 )
您也可以进行连接,但我认为速度会较慢。+1这似乎与我的快速原型配合得很好。最后我对分类做了很多操作。主要是因为我给了用户很多选项来缩小分类范围以过滤他们的结果。我发现,首先将类别作为临时表,然后在临时表上执行用户过滤器更容易。这是个坏主意吗?@John:因为创建临时表会调用写操作(并消耗空间),所以我认为这是个坏主意。如果您所做的只是操作过滤器,那么上面的语句可能会更快并节省资源。缩小搜索范围甚至可以在应用程序本身中完成,而无需往返数据库服务器。我尝试像您所说的那样编制索引,我有一个唯一的(product\u tag\u map.product\u id,product\u tag\u map.tag\u id)
,然后当我向(product\u tag\u map.tag\u id)
添加索引时。它允许我这样做,但我从phpmyadmin得到了这样的警告:UNIQUE和INDEX键不应该同时为列tag\u id设置
@John Isaacks:您想要的是(product\u id,tag\u id)
上的聚集索引(主键),而不是唯一键。这用于使用产品标识
-标签标识
组合进行查找,以及仅用于产品标识
-查找。对于tag\u id
-查找,您需要该列上的另一个(标准)索引。谢谢,我不太确定如何执行此操作,我更新了我的问题以包括我的创建表。您能告诉我如何修改它以获得正确的索引吗?