Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Вот какая ситуация. Имеем табличку users ( user_id serial, user_name varchar ). Здесь хранятся записи о пользователях. Каждая запись - один пользователь. Пример: 1 | Вася 2 | Гоша Имеем табличку tags ( tag_id serial, tag_name varchar). Здесь хранятся теги пользователя (интересы). Т.е. ключевые слова, которые могут быть в БД. Пример: 1 | Интернет 2 | Компьютеры 3 | Кино 4 | Пиво 5 | Лажа Имеем табличку usertags ( ref_id serial, user integer, tag integer). Здесь хранятся связи пользователей и тегов. Поле ref_id - просто первичный ключ Пример: 1 | 1 | 1 /* Вася любит Интернет */ 2 | 1 | 3 /* Вася любит Кино */ 3 | 1 | 4 /* Вася любит Пиво*/ 4 | 2 | 1 /* Гоша любит Интернет */ 5 | 2 | 4 /* Гоша любит Пиво */ 6 | 2 | 5 /* Гоша любит Лажу */ 7 | 2 | 3 /* Гоша любит Кино */ Допустим, что там еще есть порядка трех миллионов пользователей и около десятка тысяч тегов, у каждого пользователя есть свои интересы. У пользователей эти интересы могут пересекаться. Вопрос. Какой нужно придумать SQL-запрос, чтобы, имея заданный набор тегов, найти тех пользователей, у которых тоже имеются такие теги. При этом полное совпадение не обязательно, т.е. если я ищу по тегам "Пиво" и "Лажа", мне должны попасться все пользователи, у которых есть этот тег, но у них могут быть при этом и другие теги. Делаю всё это в PostgreSQL. Помогите, если знаете как. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 00:23 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Михаил Кечиновесли я ищу по тегам "Пиво" и "Лажа", мне должны попасться все пользователи, у которых есть этот тег, но у них могут быть при этом и другие теги.Имеется ввиду, что должны быть ОБА этих тега ОБЯЗАТЕЛЬНО, но не обязательно они будут единственными тегами у пользователя? Или достаточно одного из двух? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 00:56 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Желательно потом реализовать И и ИЛИ, но сейчас требуется только И. Т.е. чтобы оба тега были. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 10:22 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
например так. не проверял. select * from users as u join ( select user from usertags where tag=4 ) as t4 on (u.user_id=t4.user) -- пиво join ( select user from usertags where tag=5 ) as t5 on (u.user_id=t5.user) -- лажа ; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 10:47 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
А если я не знаю конкретные теги, которые мне нужны? К примеру, я знаю идентификатор пользователя, у которого есть набор тегов. Я хочу найти пользователей, которые имеют те же теги (а может быть дополнительно и другие), которые имеет пользователь №1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 11:14 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
К примеру, вот что я придумал: SELECT DISTINCT user FROM usertags WHERE tag IN ( SELECT tag FROM usertags WHERE user = 1 ) 1. Выбираем идентификаторы тегов, которые имеются у пользователя № 1 (можем подставить любого) 2. Выбираем идентификаторы пользователей из таблички связи тегов и пользователей, у которых идентификатор тега имеется в найденных тегах пользователя 1. Это позволяет получить идентификаторы пользователей по ИЛИ. Как бы сделать, чтобы еще и по И было? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 11:30 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
попробуйте примерно так select user, count(*) as tnum from ( select tag from usertags where user = ? ) as t1 natural join usertags as t2 group by user having tnum = ( select count(*) from usertags where user = ? ); можно сделать "нечеткое И" заменив having на order by tnum desc. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 11:40 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
В голову пришла шальная мысль. Добавить юзеру поле, какое-нибудь tag_hash. Заполнять его на триггере при изменении его тэгов. Заполнять следующим образом... в общем степенями двойки, где степени - id тэгов. Т.е. для 1 | 1 | 1 /* Вася любит Интернет */ 2 | 1 | 3 /* Вася любит Кино */ 3 | 1 | 4 /* Вася любит Пиво*/ для Васи получаем 2 1 + 2 3 + 2 4 = 2+8+16 = 26. Далее выбираем всех, у кого побитовое произведение дает тоже число. Т.е. 26 присутствует в полной мере. Забыл битовое умножение в постгресе, но вообщем это выглдело бы так 1. Берем это число для образцового юзера - templ_user Код: plaintext Код: plaintext Опять же - если нужно нечеткое И, то результат должен быть равен не templ_hash, а просто больше нуля - т.е. хоть одно из этого присутствует. Можно написать процедуру, которая будет возвращать набор записей, принимая параметром образцового юзера (или по желанию уже полученый templ_hash) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 12:46 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Спасибо, я попробую сегодня и то и другое. Но во втором случае - что будет, если номер тега будет № 10000 ? Слов-то много может быть. Циферка великовата получается: 2 10000 = 1,9950631168807583848837421626836e+3010 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2008, 18:08 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
авторselect user, count(*) as tnum from ( select tag from usertags where user = ? ) as t1 natural join usertags as t2 group by user having tnum = ( select count(*) from usertags where user = ? ); В этом запросе ругается на алиас tnum в конструкции having tnum ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2008, 17:19 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Михаил КечиновВ этом запросе ругается на алиас tnum в конструкции having tnum having count(*) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2008, 17:43 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
А так я пробовал, выдает ноль строк. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2008, 20:00 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Михаил КечиновА так я пробовал, выдает ноль строк.вы ошиблись Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2008, 11:02 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
Спасибо. Я попробую ваш пример. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.01.2008, 02:36 |
|
||
|
Поиск при связях "многие ко многим"
|
|||
|---|---|---|---|
|
#18+
я совершенно согласен с pamirВ голову пришла шальная мысль. Добавить юзеру поле, какое-нибудь tag_hash. Заполнять его на триггере при изменении его тэгов... и хотел бы добавить, что hash можно сравнивань не только по условию "=", а (вспомнив МНК (метод наименьших квадратов: 1 курс 2й семестер) - выдавать список совпадений по увеличению расхождений. гдето так: ... ORDER BY min( ( hash - hash_of_the_user )^2 ) -- это степень совпадения т.к. такой select требует клаузы GROUP BY, которая может длится долго, рекомедую хранить степень совпадения в отдельной таблице и пересчитывать ее или по тригеру или регулярно по (cron'у), но не непосредственно перед быдачей пользователю. ну и конечно число юзеров превышает (и намного) число всевозможный кашей, то и их можно вынести в отдельную таблицу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.01.2008, 14:28 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=35090917&tid=2004673]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
69ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 241ms |
| total: | 396ms |

| 0 / 0 |
