EXISTS в MySQL — практические приёмы фильтраций и проверок

100 приёмов MySQL EXISTS: WHERE, NOT EXISTS, UPDATE/DELETE, антиджойны, агрегаты, двойные проверки.

 🟢 EXISTS в MySQL. Введение

EXISTS в MySQL — булев предикат, который возвращает TRUE, если подзапрос выдаёт хотя бы одну строку. Он идеально подходит для проверки наличия связанных данных, поиска отсутствующих связей через NOT EXISTS, а также для точечных UPDATE/DELETE с коррелированными подзапросами.

Синтаксис

SELECT col_list
FROM table_outer
WHERE EXISTS (
  SELECT 1
  FROM table_inner
  WHERE table_inner.ref_id = table_outer.id
);
UPDATE table t
SET flag = 1
WHERE EXISTS (
  SELECT 1
  FROM other o
  WHERE o.t_id = t.id
);
DELETE FROM table t
WHERE NOT EXISTS (
  SELECT 1
  FROM other o
  WHERE o.t_id = t.id
);

Типовая конструкция

SELECT c.id, c.name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

100 примеров

1. Покупатели с заказами

SELECT *
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

2. Товары с отзывами

SELECT *
FROM products p
WHERE EXISTS (
  SELECT 1
  FROM reviews r
  WHERE r.product_id = p.id
);

3. Посты с комментариями

SELECT *
FROM posts p
WHERE EXISTS (
  SELECT 1
  FROM comments c
  WHERE c.post_id = p.id
);

4. Пользователи с активными сессиями

SELECT *
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM sessions s
  WHERE s.user_id = u.id AND s.active=1
);

5. Кампании с кликами

SELECT *
FROM campaigns c
WHERE EXISTS (
  SELECT 1
  FROM clicks cl
  WHERE cl.campaign_id = c.id
);

6. Видео с лайками

SELECT *
FROM videos v
WHERE EXISTS (
  SELECT 1
  FROM likes l
  WHERE l.video_id = v.id
);

7. Города с достопримечательностями

SELECT *
FROM cities c
WHERE EXISTS (
  SELECT 1
  FROM sights s
  WHERE s.city_id = c.id
);

8. Фильмы с рецензиями

SELECT *
FROM movies m
WHERE EXISTS (
  SELECT 1
  FROM reviews r
  WHERE r.movie_id = m.id
);

9. Курсы с экзаменами

SELECT *
FROM courses c
WHERE EXISTS (
  SELECT 1
  FROM exams e
  WHERE e.course_id = c.id
);

10. Студенты с оценками A

SELECT *
FROM students s
WHERE EXISTS (
  SELECT 1
  FROM grades g
  WHERE g.student_id = s.id AND g.grade='A'
);

11. Сенсоры с аномалиями

SELECT *
FROM sensors s
WHERE EXISTS (
  SELECT 1
  FROM anomalies a
  WHERE a.sensor_id = s.id
);

12. Сервисы с ошибками

SELECT *
FROM services s
WHERE EXISTS (
  SELECT 1
  FROM logs l
  WHERE l.service_id = s.id AND l.level='error'
);

13. Проекты с активными задачами

SELECT *
FROM projects p
WHERE EXISTS (
  SELECT 1
  FROM tasks t
  WHERE t.project_id = p.id AND t.status='doing'
);

14. Менеджеры с подчинёнными

SELECT *
FROM employees m
WHERE EXISTS (
  SELECT 1
  FROM employees e
  WHERE e.manager_id = m.id
);

15. Склады с остатками

SELECT *
FROM warehouses w
WHERE EXISTS (
  SELECT 1
  FROM stock s
  WHERE s.warehouse_id = w.id AND s.qty>0
);

16. Страны с аэропортами

SELECT *
FROM countries c
WHERE EXISTS (
  SELECT 1
  FROM airports a
  WHERE a.country_id = c.id
);

17. Клиенты со счетами

SELECT *
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM invoices i
  WHERE i.customer_id = c.id
);

18. Задачи с подзадачами

SELECT *
FROM tasks t
WHERE EXISTS (
  SELECT 1
  FROM subtasks s
  WHERE s.task_id = t.id
);

19. Устройства с обновлениями

SELECT *
FROM devices d
WHERE EXISTS (
  SELECT 1
  FROM updates u
  WHERE u.device_id = d.id
);

20. Посты с тегами

SELECT *
FROM posts p
WHERE EXISTS (
  SELECT 1
  FROM post_tags pt
  WHERE pt.post_id = p.id
);

21. Авторы с опубликованными постами

SELECT *
FROM authors a
WHERE EXISTS (
  SELECT 1
  FROM posts p
  WHERE p.author_id = a.id AND p.published=1
);

22. Платежи с возвратами

SELECT *
FROM payments p
WHERE EXISTS (
  SELECT 1
  FROM refunds r
  WHERE r.payment_id = p.id
);

23. Пользователи с 2FA

SELECT *
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM auth_factors af
  WHERE af.user_id = u.id AND af.type='2fa'
);

24. Чаты с непрочитанными сообщениями

SELECT *
FROM chats c
WHERE EXISTS (
  SELECT 1
  FROM messages m
  WHERE m.chat_id = c.id AND m.read=0
);

25. Магазины с продажами сегодня

SELECT *
FROM shops s
WHERE EXISTS (
  SELECT 1
  FROM sales sl
  WHERE sl.shop_id = s.id AND DATE(sl.created_at)=CURDATE()
);

26. API с медленным откликом

SELECT *
FROM apis a
WHERE EXISTS (
  SELECT 1
  FROM metrics m
  WHERE m.api_id = a.id AND m.latency_ms>1000
);

27. Репозитории с открытыми PR

SELECT *
FROM repos r
WHERE EXISTS (
  SELECT 1
  FROM pull_requests pr
  WHERE pr.repo_id = r.id AND pr.open=1
);

28. Школы с ≥500 учениками

SELECT *
FROM schools s
WHERE EXISTS (
  SELECT 1
  FROM students st
  WHERE st.school_id = s.id
);

29. События с проданными билетами

SELECT *
FROM events e
WHERE EXISTS (
  SELECT 1
  FROM tickets t
  WHERE t.event_id = e.id
);

30. Пользователи с подпиской PRO

SELECT *
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM subscriptions s
  WHERE s.user_id = u.id AND s.plan='pro'
);

Ещё примеры

31. Клиенты без заказов

SELECT *
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

32. Товары без отзывов

SELECT *
FROM products p
WHERE NOT EXISTS (
  SELECT 1
  FROM reviews r
  WHERE r.product_id = p.id
);

33. Посты без комментариев

SELECT *
FROM posts p
WHERE NOT EXISTS (
  SELECT 1
  FROM comments c
  WHERE c.post_id = p.id
);

34. Пользователи без активных сессий

SELECT *
FROM users u
WHERE NOT EXISTS (
  SELECT 1
  FROM sessions s
  WHERE s.user_id = u.id AND s.active=1
);

35. Кампании без кликов

SELECT *
FROM campaigns c
WHERE NOT EXISTS (
  SELECT 1
  FROM clicks cl
  WHERE cl.campaign_id = c.id
);

36. Города без достопримечательностей

SELECT *
FROM cities c
WHERE NOT EXISTS (
  SELECT 1
  FROM sights s
  WHERE s.city_id = c.id
);

37. Фильмы без рецензий

SELECT *
FROM movies m
WHERE NOT EXISTS (
  SELECT 1
  FROM reviews r
  WHERE r.movie_id = m.id
);

38. Курсы без экзаменов

SELECT *
FROM courses c
WHERE NOT EXISTS (
  SELECT 1
  FROM exams e
  WHERE e.course_id = c.id
);

39. Сенсоры без аномалий

SELECT *
FROM sensors s
WHERE NOT EXISTS (
  SELECT 1
  FROM anomalies a
  WHERE a.sensor_id = s.id
);

40. Проекты без задач

SELECT *
FROM projects p
WHERE NOT EXISTS (
  SELECT 1
  FROM tasks t
  WHERE t.project_id = p.id
);

41. Сотрудники без подчинённых

SELECT *
FROM employees m
WHERE NOT EXISTS (
  SELECT 1
  FROM employees e
  WHERE e.manager_id = m.id
);

42. Склады без остатков

SELECT *
FROM warehouses w
WHERE NOT EXISTS (
  SELECT 1
  FROM stock s
  WHERE s.warehouse_id = w.id AND s.qty>0
);

43. Страны без аэропортов

SELECT *
FROM countries c
WHERE NOT EXISTS (
  SELECT 1
  FROM airports a
  WHERE a.country_id = c.id
);

44. Клиенты без неоплаченных счетов

SELECT *
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM invoices i
  WHERE i.customer_id = c.id AND i.paid=0
);

45. Задачи без подзадач

SELECT *
FROM tasks t
WHERE NOT EXISTS (
  SELECT 1
  FROM subtasks s
  WHERE s.task_id = t.id
);

46. Устройства без обновлений

SELECT *
FROM devices d
WHERE NOT EXISTS (
  SELECT 1
  FROM updates u
  WHERE u.device_id = d.id
);

47. Посты без тегов

SELECT *
FROM posts p
WHERE NOT EXISTS (
  SELECT 1
  FROM post_tags pt
  WHERE pt.post_id = p.id
);

48. Платежи без возвратов

SELECT *
FROM payments p
WHERE NOT EXISTS (
  SELECT 1
  FROM refunds r
  WHERE r.payment_id = p.id
);

49. Чаты без непрочитанных сообщений

SELECT *
FROM chats c
WHERE NOT EXISTS (
  SELECT 1
  FROM messages m
  WHERE m.chat_id = c.id AND m.read=0
);

50. Магазины без продаж сегодня

SELECT *
FROM shops s
WHERE NOT EXISTS (
  SELECT 1
  FROM sales sl
  WHERE sl.shop_id = s.id AND DATE(sl.created_at)=CURDATE()
);

Ещё примеры

51. Активировать клиентов с заказами

UPDATE customers c
SET status='active'
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id=c.id
);

52. Удалить товары без продаж

DELETE FROM products p
WHERE NOT EXISTS (
  SELECT 1
  FROM order_items oi
  WHERE oi.product_id=p.id
);

53. Отметить кампании с кликами

UPDATE campaigns c
SET status='engaged'
WHERE EXISTS (
  SELECT 1
  FROM clicks cl
  WHERE cl.campaign_id=c.id
);

54. Деактивировать сотрудников без задач

UPDATE employees e
SET active=0
WHERE NOT EXISTS (
  SELECT 1
  FROM tasks t
  WHERE t.employee_id=e.id
);

55. Подтвердить заказы с оплатами

UPDATE orders o
SET paid=1
WHERE EXISTS (
  SELECT 1
  FROM payments p
  WHERE p.order_id=o.id
);

56. Удалить события без билетов

DELETE FROM events e
WHERE NOT EXISTS (
  SELECT 1
  FROM tickets t
  WHERE t.event_id=e.id
);

57. Активировать проекты с задачами

UPDATE projects p
SET active=1
WHERE EXISTS (
  SELECT 1
  FROM tasks t
  WHERE t.project_id=p.id
);

58. Удалить файлы без загрузок

DELETE FROM files f
WHERE NOT EXISTS (
  SELECT 1
  FROM downloads d
  WHERE d.file_id=f.id
);

59. Включить сенсоры с измерениями

UPDATE sensors s
SET active=1
WHERE EXISTS (
  SELECT 1
  FROM measurements m
  WHERE m.sensor_id=s.id
);

60. Удалить клиентов без оплат

DELETE FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM payments p
  WHERE p.customer_id=c.id
);

61. Пометить студентов с оценками

UPDATE students s
SET status='graded'
WHERE EXISTS (
  SELECT 1
  FROM grades g
  WHERE g.student_id=s.id
);

62. Удалить блоги без постов

DELETE FROM blogs b
WHERE NOT EXISTS (
  SELECT 1
  FROM posts p
  WHERE p.blog_id=b.id
);

63. Включить API с вызовами

UPDATE apis a
SET active=1
WHERE EXISTS (
  SELECT 1
  FROM calls c
  WHERE c.api_id=a.id
);

64. Удалить склады без товаров

DELETE FROM warehouses w
WHERE NOT EXISTS (
  SELECT 1
  FROM stock s
  WHERE s.warehouse_id=w.id
);

65. Включить роли с правами

UPDATE roles r
SET enabled=1
WHERE EXISTS (
  SELECT 1
  FROM permissions p
  WHERE p.role_id=r.id
);

66. Удалить страницы без комментариев

DELETE FROM pages p
WHERE NOT EXISTS (
  SELECT 1
  FROM comments c
  WHERE c.page_id=p.id
);

67. Активировать сотрудников с задачами

UPDATE employees e
SET active=1
WHERE EXISTS (
  SELECT 1
  FROM tasks t
  WHERE t.employee_id=e.id
);

68. Удалить пользователей без сессий

DELETE FROM users u
WHERE NOT EXISTS (
  SELECT 1
  FROM sessions s
  WHERE s.user_id=u.id
);

69. Пометить заказы с доставкой

UPDATE orders o
SET shipped=1
WHERE EXISTS (
  SELECT 1
  FROM shipments s
  WHERE s.order_id=o.id
);

70. Удалить книги без авторов

DELETE FROM books b
WHERE NOT EXISTS (
  SELECT 1
  FROM authors a
  WHERE a.book_id=b.id
);

Ещё примеры

71. Города где есть театры и музеи

SELECT id, name
FROM cities c
WHERE EXISTS (
  SELECT 1
  FROM theatres t
  WHERE t.city_id=c.id
) AND EXISTS (
  SELECT 1
  FROM museums m
  WHERE m.city_id=c.id
);

72. Пользователи с активной подпиской и платежом

SELECT id, email
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM subscriptions s
  WHERE s.user_id=u.id AND s.active=1
) AND EXISTS (
  SELECT 1
  FROM payments p
  WHERE p.user_id=u.id
);

73. Сервисы с error и fatal логами

SELECT id, name
FROM services s
WHERE EXISTS (
  SELECT 1
  FROM logs l
  WHERE l.service_id=s.id AND l.level='error'
) AND EXISTS (
  SELECT 1
  FROM logs l2
  WHERE l2.service_id=s.id AND l2.level='fatal'
);

74. Клиенты с покупкой и возвратом

SELECT id, name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id=c.id
) AND EXISTS (
  SELECT 1
  FROM returns r
  WHERE r.customer_id=c.id
);

75. Продукты, продававшиеся в ≥2 странах

SELECT id, name
FROM products p
WHERE EXISTS (
  SELECT 1
  FROM sales s
  WHERE s.product_id=p.id
  GROUP BY s.country
  HAVING COUNT(DISTINCT s.country)>=2
);

76. Школы с олимпиадами и кружками

SELECT id, name
FROM schools s
WHERE EXISTS (
  SELECT 1
  FROM olympiads o
  WHERE o.school_id=s.id
) AND EXISTS (
  SELECT 1
  FROM clubs c
  WHERE c.school_id=s.id
);

77. Сайты без 5xx ошибок

SELECT id, host
FROM sites s
WHERE NOT EXISTS (
  SELECT 1
  FROM logs l
  WHERE l.site_id=s.id AND l.status BETWEEN 500 AND 599
);

78. Водители без нарушений за год

SELECT id, name
FROM drivers d
WHERE NOT EXISTS (
  SELECT 1
  FROM violations v
  WHERE v.driver_id=d.id AND v.at>=CURDATE()-INTERVAL 1 YEAR
);

79. Курсы где есть экзамены и домашние

SELECT id, title
FROM courses c
WHERE EXISTS (
  SELECT 1
  FROM exams e
  WHERE e.course_id=c.id
) AND EXISTS (
  SELECT 1
  FROM homeworks h
  WHERE h.course_id=c.id
);

80. Компании с >100 сотрудников

SELECT id, name
FROM companies c
WHERE EXISTS (
  SELECT 1
  FROM employees e
  WHERE e.company_id=c.id
  GROUP BY e.company_id
  HAVING COUNT(*)>100
);

81. Посты с лайками за неделю

SELECT id, title
FROM posts p
WHERE EXISTS (
  SELECT 1
  FROM likes l
  WHERE l.post_id=p.id AND l.created_at>=NOW()-INTERVAL 7 DAY
);

82. Проекты со сроками в будущем

SELECT id, name
FROM projects p
WHERE EXISTS (
  SELECT 1
  FROM deadlines d
  WHERE d.project_id=p.id AND d.due_at>NOW()
);

83. Товары с фото и видео

SELECT id, name
FROM products p
WHERE EXISTS (
  SELECT 1
  FROM uploads u1
  WHERE u1.product_id=p.id AND u1.kind='photo'
) AND EXISTS (
  SELECT 1
  FROM uploads u2
  WHERE u2.product_id=p.id AND u2.kind='video'
);

84. Пользователи где есть и логин, и покупка сегодня

SELECT id
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM logins l
  WHERE l.user_id=u.id AND DATE(l.at)=CURDATE()
) AND EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.user_id=u.id AND DATE(o.created_at)=CURDATE()
);

85. Сенсоры с двумя типами аномалий

SELECT id
FROM sensors s
WHERE EXISTS (
  SELECT 1
  FROM anomalies a
  WHERE a.sensor_id=s.id AND a.kind='spike'
) AND EXISTS (
  SELECT 1
  FROM anomalies a2
  WHERE a2.sensor_id=s.id AND a2.kind='drift'
);

86. Маршруты с активными поездками и отзывами

SELECT id
FROM routes r
WHERE EXISTS (
  SELECT 1
  FROM trips t
  WHERE t.route_id=r.id AND t.active=1
) AND EXISTS (
  SELECT 1
  FROM reviews rv
  WHERE rv.route_id=r.id
);

87. Фильмы с премиями и кассой > 1М

SELECT id, title
FROM movies m
WHERE EXISTS (
  SELECT 1
  FROM awards a
  WHERE a.movie_id=m.id
) AND EXISTS (
  SELECT 1
  FROM boxoffice b
  WHERE b.movie_id=m.id AND b.amount>1000000
);

88. Игры с турнирами и таблицами лидеров

SELECT id, title
FROM games g
WHERE EXISTS (
  SELECT 1
  FROM tournaments t
  WHERE t.game_id=g.id
) AND EXISTS (
  SELECT 1
  FROM leaderboards lb
  WHERE lb.game_id=g.id
);

89. Заявки с приложениями и комментариями

SELECT id
FROM tickets t
WHERE EXISTS (
  SELECT 1
  FROM attachments a
  WHERE a.ticket_id=t.id
) AND EXISTS (
  SELECT 1
  FROM comments c
  WHERE c.ticket_id=t.id
);

90. Клиенты без отменённых заказов

SELECT id, name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id=c.id AND o.status='cancelled'
);

91. Товары без возвратов за 90 дней

SELECT id, name
FROM products p
WHERE NOT EXISTS (
  SELECT 1
  FROM returns r
  WHERE r.product_id=p.id AND r.created_at>=NOW()-INTERVAL 90 DAY
);

92. Ученики без двоек

SELECT id, name
FROM students s
WHERE NOT EXISTS (
  SELECT 1
  FROM grades g
  WHERE g.student_id=s.id AND g.score<50
);

93. Сервисы без критических алертов

SELECT id, name
FROM services s
WHERE NOT EXISTS (
  SELECT 1
  FROM alerts a
  WHERE a.service_id=s.id AND a.severity='critical'
);

94. Карты клиентов с покупками в двух валютах

SELECT id
FROM cards c
WHERE EXISTS (
  SELECT 1
  FROM payments p
  WHERE p.card_id=c.id
  GROUP BY p.currency
  HAVING COUNT(DISTINCT p.currency)>=2
);

95. Флажок наличия комментариев в SELECT

SELECT p.id, (EXISTS (
  SELECT 1
  FROM comments c
  WHERE c.post_id=p.id
)) AS has_comments
FROM posts p;

Ещё примеры

96. Быстрый тест через LIMIT 1

SELECT id
FROM users u
WHERE EXISTS (
  SELECT 1
  FROM logins l
  WHERE l.user_id=u.id
  LIMIT 1
);

97. Признак крупного заказа в выборке

SELECT u.id,
       (EXISTS (
         SELECT 1
         FROM orders o
         WHERE o.user_id=u.id AND o.total>100
       )) AS has_big_order
FROM users u;

98. Антиджойн через NOT EXISTS

SELECT p.id
FROM products p
WHERE NOT EXISTS (
  SELECT 1
  FROM reviews r
  WHERE r.product_id=p.id
);

99. С агрегатами в подзапросе

SELECT c.id, c.name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id=c.id
  GROUP BY o.customer_id
  HAVING SUM(o.total)>5000
);

100. Фильтр по наличию фото у автора

SELECT a.id, a.name
FROM authors a
WHERE EXISTS (
  SELECT 1
  FROM uploads u
  WHERE u.author_id=a.id AND u.kind='avatar'
);

Заключение

EXISTS — удобный способ проверять наличие данных без лишних соединений. Используйте его для фильтрации, антиджойнов, условных UPDATE/DELETE и составных проверок.

Справка: официальная документация MySQL.


 

Понравилась статья? Поделиться с друзьями: