Fernus
@Fernus
Техник - Механик :)

Запрос в MySQL. Есть идея?

Структура таблицы:
id | link_id | flag

Пример данных:
1 | 111 | 1
2 | 111 | 1
3 | 111 | 0
4 | 111 | 1
5 | 222 | 1
6 | 222 | 1
7 | 222 | 1

8 | 333 | 1
9 | 333 | 0

Суть задачи:
Выбрать все записи у которых flag равен 1 у всех записей с одинаковыми link_id.
1,2,3,4 - имеют один link_id, но не у вссех flag равен 1.
8,9 - та же ситуация...
5,6,7 - подходят под условие.

Можно текстом хотя бы направление дать...сам запрос думаю составлю...чёт затупил над такой простой ситуацией...
  • Вопрос задан
  • 145 просмотров
Решения вопроса 3
Melkij
@Melkij
PostgreSQL DBA
Для поиска самих link_id
select link_id from tablename
group by link_id
having count(*) = sum(flag  = 1)

Либо
select id from links
where exists(select null from tablename where flag  = 1 and link_id = links.id) -- возможно это условие вам по задаче не нужно
and not exists(select null from tablename where flag != 1 and link_id = links.id)


Вычитывать сами строки можно попробовать через
select ...
from tablename t
where t.flag = 1
and not exists(select null from tablename sq where sq.link_id = t.link_id and sq.flag != 1)


При том, какой из вариантов эффективнее - критично зависит от распределения данных. При большой числе различающихся link_id с малым числом строк на каждый link_id и малым ожидаемом числе подходящих строк под задачу может быть эффективнее именно
select ... from tablename t where t.link_id in (
select q.link_id from tablename q
group by q.link_id
having count(*) = sum(flag  = 1)
)


При большом числе строк на каждый link_id и малом числе разных link_id может оказаться разумнее аналогично сначала достать link_id удовлетворяющие условию и по ним уже доставать данные.

Третий запрос по ожиданию лучше отзовётся на случай малого числа flag = 1 строк в таблице.

Самый быстрый на чтение вариант, впрочем, всё равно не выполнять обработку этого фильтра налету, а каким-то образом его материализовать и хранить предварительно рассчитанным.
Ответ написан
trapwalker
@trapwalker
Программист, энтузиаст
например так:
SELECT t.*
FROM my_table t
WHERE NOT EXISTS(
  SELECT null FROM my_table t2 WHERE t2.link_id = t.link_id and t2.flag=0
)

Можно и с джойном:
WITH tt AS(SELECT DISTINCT link_id WHERE flag = 0)
SELECT t1.*
FROM
    my_table t1
    LEFT JOIN tt t2 ON t2.link_id = t.1link_id
WHERE t2.link_id is None
Ответ написан
shabelski89
@shabelski89
engineer
Если нужно, прям как выделено жирным, то подзапросом выбираем записи с link_id = 0 в поле flag, а условием выводим все записи не в этом диапазоне.
SELECT * FROM new_table 
WHERE 
link_id NOT IN (SELECT DISTINCT(link_id) FROM new_table WHERE flag=0);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы