我有一个页面,允许人们比较数据库中的项目。每次比较的项目数量不固定。我使用两列表来存储他们的比较记录和时间戳,作为将它们组合在一起的方法。
假设我有product_id 304
和308
以及306
,我如何检查它们是否作为同一组存在于数据库中?我不确定如何检查多个product_ids的组合,我正在寻找类似的东西:
输出:
product_id name
306|308|304 D|E|C
以下是查询:
SELECT product_id,name
FROM (
SELECT
GROUP_CONCAT(c.product_id SEPARATOR "|") AS product_id,
GROUP_CONCAT(p.name SEPARATOR "|") AS name
FROM compare c
INNER JOIN product p ON p.product_id = c.product_id
GROUP BY c.timestamp
ORDER BY c.timestamp
/* How to do a where clause here? WHERE p.product_id = 306 AND p.product_id = 308 AND p.product_id = 304 */
)e
GROUP BY product_id
CREATE TABLE compare
(`product_id` int,`timestamp` timestamp)
;
INSERT INTO compare
(`product_id`,`timestamp`)
VALUES
(300,'2015-01-12 19:04:13'),
(302,'2015-01-12 19:04:13'),
(304,'2015-01-12 19:06:24'),
(306,'2015-01-12 19:06:24'),
(308,'2015-01-12 19:06:24'),
(310,'2015-01-12 19:08:40'),
(312,'2015-01-12 19:08:40'),
(314,'2015-01-12 19:08:40'),
(316,'2015-01-12 19:08:40'),
(302,'2015-01-12 19:10:50'),
(316,'2015-01-12 19:10:50')
;
CREATE TABLE product
(`product_id` int,`name` varchar(30))
;
INSERT INTO product
(`product_id`,`name`)
VALUES
(300,'A'),
(302,'B'),
(304,'C'),
(306,'D'),
(308,'E'),
(310,'F'),
(312,'G'),
(314,'H'),
(316,'I')
;
答案 0 :(得分:1)
如果我的意图是正确的,你想要保留一份比较列表,并且如果发生某种比较就能回答问题,并且可能会对此列表进行重复数据删除。
你的方法不起作用。
您需要的是有效地将product_ids设置为某个标识符。这是可能的方法之一:
CREATE TABLE comparison (
id int not null auto_increment,
created_at timestamp default current_timestamp,
hash varchar(16), -- or some other type depending the hash function of your choice
primary key (id),
key (hash)
);
CREATE TABLE comparison item (
comparison_id int not null,
product_id int not null,
primary key (comparison_id, product_id)
);
在创建新比较(或检查是否已存在)时,您计算product_ids集的哈希函数,比如说你对product_ids进行排序,连接它们,得到结果的md5并以十六进制表示存储一半字符串(它更短,但仍然足够。)
如果要检查已存储的比较,首先要检查是否存在具有给定哈希的记录。
如果是,那么您可以使用相应的comparison_id从第二个表中获取所有行,以确保您没有幸运地遇到冲突。
如果没有,这意味着你以前从未遇到过这个集。
使用此结构,您仍然可以在创建比较时存储时间戳,并检查是否曾使用过单个product_id(为此,您需要在第二个表中另外添加key(product_id)
。