Нахождение похожей записи в рамках одной таблицы

Overcast

Новичок
Нахождение похожей записи в рамках одной таблицы

Есть таблица `relations`. Выглядит приблизительно так:
--------------------------
|ID|ITEM_ID|CAT_ID|
--------------------------
|1 |1 |104 |
|2 |1 |108 |
|3 |1 |111 |
|4 |2 |102 |
|5 |2 |108 |
|6 |2 |111 |
|. |. |... |
--------------------------

Это связывающая таблица между таблицами `items` ( ключ ITEM_ID) и `categories` ( ключ CAT_ID ). Каждому объекту (ITEM_ID) присвоено несколько значений категорий (CAT_ID). Возможно с помощью запроса MYSQL вывести все записи ITEM_ID у которых CAT_ID будет равен нескольким значения одновременно (например и 108 и 111, как у записей ITEM_ID 1 и 2)?
 

Overcast

Новичок
Автор оригинала: findnext
меню делаешь, да?

-~{}~ 16.12.08 19:25:

IN
Нет, делаю похожие записи для каталога видео. IN не подходит, если я делаю SELECT DISTINCT `item_id` FROM `relations` WHERE `cat_id` IN ( 108, 111 ), то получу записи которые содержат 108 И/ИЛИ 111, а нужно 108 И 111.
 

FractalizeR

Новичок
[sql]SELECT ITEM_ID, GROUP_CONCAT( CAST( CAT_ID AS CHAR )
ORDER BY CAT_ID
SEPARATOR ',' ) AS grp
FROM relations
GROUP BY ITEM_ID
HAVING grp = "108,111"[/sql]

Правда, это решение требует Full table scan. Но думаю, его можно оптимизировать вот так:

[sql]SELECT ITEM_ID, GROUP_CONCAT( CAST( CAT_ID AS CHAR )
ORDER BY CAT_ID
SEPARATOR ',' ) AS grp
FROM (
(

SELECT *
FROM relations
WHERE CAT_ID
IN ( 108, 111 )
) AS tmptbl
)
GROUP BY ITEM_ID
HAVING grp = "108,111"[/sql]
 

Overcast

Новичок
Не помогло :( Возвращает пустой результат

P.S. Помогло :) Это я ступил, в grp = "108,111" у меня другие значения, а я их не отсортировал по возрастанию. СПАСИБО ОГРОМНОЕ!
 

FractalizeR

Новичок
Не за что. Только обязательно проверьте, как запросы себя ведут на больших таблицах. Как бы тормозов не наделать.
 

Overcast

Новичок
Таблица из 12460 элементов. Реальные запросы и статистика:

SELECT `cinemaid`, GROUP_CONCAT( CAST( `catid` AS CHAR ) ORDER BY `catid` SEPARATOR ',' ) AS grp FROM `catalog_categories` GROUP BY `cinemaid` HAVING grp = "40,102,109,110,112,132,133,144,170"

Отображает строки 0 - 0 (1 всего, запрос занял 0.0249 сек.)

SELECT `cinemaid`, GROUP_CONCAT( CAST( `catid` AS CHAR ) ORDER BY `catid` SEPARATOR ',' ) AS grp FROM ( ( SELECT * FROM `catalog_categories` WHERE `catid` IN ( 40, 102, 109, 110, 112, 132, 133, 144, 170 ) ) AS tmptbl ) GROUP BY `cinemaid` HAVING grp = "40,102,109,110,112,132,133,144,170"

Отображает строки 0 - 0 (1 всего, запрос занял 0.0127 сек.)

Второй вариант действительно быстрее! Сервер довольно мощный, так что сложно судить по скорости %) Но на всякий пожарный кеширую полученный результат на 30 дней :)
 
Сверху