2015-01-12 3 views
0

Fiddle Exampleпроверить, если комбинации (группа по временной метке) существуют в MySQL

У меня есть страница, которая позволяет людям сравнивать элементы из базы данных. Количество элементов для каждого сравнения не фиксировано. Я использую таблицу с двумя столбцами для хранения своих записей сравнения с меткой времени, чтобы сгруппировать их вместе.

Предположим, у меня есть 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') 

; 
+1

WHERE n IN (x, y, z) GROUP BY HAVING COUNT (*) = 3 – Strawberry

+1

Вы не должны использовать временные метки как уникальные идентификаторы, потому что невозможно гарантировать их уникальность. –

ответ

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 из результат и сохраните половину строки в шестнадцатеричном представлении (она короче и все равно будет достаточно).

Если вы проверяете уже сохраненное сравнение, вы сначала проверяете, существует ли запись с заданным хешем.

Если да, то вы можете получить все строки из второй таблицы с помощью соответствующего сравнения_ид, чтобы убедиться, что вам не повезло столкнуться с столкновением.

Если нет, это означает, что вы никогда не сталкивались с этим набором раньше.

Используя эту структуру, вы все равно можете хранить временные метки при создании сравнения и проверять, использовался ли какой-либо продукт product_id (для этого вам понадобится дополнительный key(product_id) во второй таблице).

Смежные вопросы