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.