Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Не понимаю как сделать запрос / 9 сообщений из 9, страница 1 из 1
02.01.2016, 00:29
    #39141339
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Всех с Новым Годом! :)

Помогите плиз сделать запрос.

Есть такая таблица:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
id  | thread_id     | user_id
---------------------------
6   |     3         |     3
14  |     3         |     2
7   |     4         |    28
8   |     4         |     2
9   |     5         |    27
10  |     5         |    28
11  |     6         |     2
12  |     6         |    27
26  |     11        |     2
27  |     11        |     3
28  |     11        |    61
29  |     11        |    62



Нужно сделать запрос и выдать только те thread_id в которых есть все запрашиваемые user_id.

Например по таблице выше запрашиваю user_id=2,3 должно выдать thread_id=3,11

Помогите плиз :(
...
Рейтинг: 0 / 0
02.01.2016, 01:44
    #39141346
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Нашел такое решение:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT thread_id FROM table
                          WHERE user_id IN (2,3)
GROUP BY thread_id
HAVING count(thread_id) = 2;

-- HAVING count(thread_id) = 2  - это кол-во элементов в IN 



Работает! Может кто что скажет еще?
...
Рейтинг: 0 / 0
02.01.2016, 02:08
    #39141350
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Closius,

Реляционное деление. Мне вот это пояснение нравиться.
И я предпочитаю вариант с двойным отрицанием (он универсален — не надо подставлять кол-во элементов в IN выражении):

Код: plaintext
Не должно быть веток обсуждения, в которых не участвовали бы заданные пользователи (двойное отрицание).

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
WITH s(id,thread_id,user_id) AS (
  VALUES (6::int,3::int,3::int),
    (14,3,2),(7,4,28),(8,4,2),
    (9,5,27),(10,5,28),(11,6,2),
    (12,6,27),(26,11,2),(27,11,3),
    (28,11,61),(29,11,62)
)
SELECT * FROM s s1
 WHERE NOT EXISTS (
    SELECT 1 FROM s s2
     WHERE s2.user_id IN (2,3)
       AND NOT EXISTS (
        SELECT 1 FROM s s3
         WHERE s3.thread_id=s1.thread_id AND s3.user_id=s2.user_id
     )
 );


Тут получается, что:
`s1` — делимое

`s2` — делитель, в данном случае та же таблица с заданным условием

`s3` — связка между ними.

Самый нижний подзапрос вернет записи, которые удовлетворяют условию. Соответственно, подзапрос второго уровня их исключит и оставит такие, которые неверны. Ну и на самом верхнем уровне остаются только искомые.
...
Рейтинг: 0 / 0
02.01.2016, 09:58
    #39141361
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
vyegorov,

вкусовщина -- страшная сила

допустим, каждый усер принял участие менее чем в 1/10000 тредов.

и, допустим, мы ищем по подмножеству менее чем 1/10000 усеров


тогда where стартера эффективно обрежет по индексу что-- то заведомо ~<1/1000
а где будет ваш not EXISTS по фуллскану ?
...
Рейтинг: 0 / 0
02.01.2016, 12:07
    #39141372
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
vyegorov,

У вас же два подзапроса, прчем подзапрос в подзапросе.. Думаю стоимость будет выше моего варианта
...
Рейтинг: 0 / 0
02.01.2016, 12:25
    #39141378
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Кстати я что еще понял, мне нужно также вывести общее кол-во user_id которые имеют одинаковый thread_id

Решил это так:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT thread_id, participants FROM 
                table AS p1,
                LATERAL (SELECT count(user_id) FROM table AS p2 WHERE p2.thread_id = p1.thread_id) AS participants
                               WHERE p1.user_id IN (2,3)
GROUP BY p1.thread_id, dd
HAVING count(p1.thread_id) = 2;



То есть сейчас выведет


Код: sql
1.
2.
3.
4.
thread_id  |  participants
---------------------------
3          |       (2)
11         |       (4)



Но запрос значительно усложнился...
...
Рейтинг: 0 / 0
02.01.2016, 13:22
    #39141390
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Только теперь другая проблема: participants получается псевдотипом record... Как его в int преобразовать или сделать так чтобы он не кастовался в рекорд?
...
Рейтинг: 0 / 0
02.01.2016, 13:27
    #39141391
Closius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
получилось:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT thread_id, participants.rr FROM 
                table AS p1,
                LATERAL (SELECT count(user_id) as rr FROM table AS p2 WHERE p2.thread_id = p1.thread_id) AS participants
                               WHERE p1.user_id IN (2,3)
GROUP BY p1.thread_id, dd
HAVING count(p1.thread_id) = 2;
...
Рейтинг: 0 / 0
03.01.2016, 14:48
    #39141590
p2.
p2.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не понимаю как сделать запрос
Closiusобщее кол-во user_id которые имеют одинаковый thread_idубрать в первом запросе where и добавить left join на список требуемых id и проверять count по user_id.
или переписать having на условный count filter по user_id in ...
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Не понимаю как сделать запрос / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]