Xpoint
   [напомнить пароль]

Выбрать группы в которых нет пользователя без подзапросов

Метки: [без меток]
2007-02-10 11:35:09 [обр] Закиров Руслан(12/343)[досье]

Классическая связка многие ко многим: Groups(id, Name), Users(id, Name, Email) и GroupMembers(Group, Member).

Нельзя использовать подзапросы, но нужно выбрать список групп, где нет пользователей удовлетворяющих какому-нибудь условию, например: Email LIKE '%@mail.ru'. Голову ломаю несколько дней, но ничего не получается.

спустя 1 час 19 минут [обр] Владимир Хоменко(2/67)[досье]
Что-то такое, я полагаю:
select g.id, g.Name, sum(if(u.Email like '%@mail.ru', 1, 0)) as bad from Groups g left join GroupMembers gm on g.id = gm.Group left join Users u on gm.Member = u.id group by g.id having bad = 0;
спустя 1 час 7 минут [обр] Закиров Руслан(12/343)[досье]
Неплохо, но совсем обойтись только объединениями и условиями можно? Я уже все прередумал и получается, что нельзя.
спустя 1 час [обр] Владимир Хоменко(2/67)[досье]

Одними обьеденениями и условиями никак не обойтись. Выборка подразумевает LEFT JOIN, поэтому результаты придется группировать, и среди отгруппированных результатов придется еще раз делать выборку по условию, которое нельзя вставить в WHERE, потому как отсекутся поля, которые необходимы для LEFT JOIN. Эту проблему не используя having решить невозможно.

Все вышесказанное IMHO

спустя 4 часа 24 минуты [обр] dacuan(0/7)[досье]
Может что-то вроде этого:
SELECT
    g.id, g.Name
FROM
    Groups AS g 
    LEFT JOIN GroupMembers AS gm on g.id = gm.Group
    LEFT JOIN (Users AS u on gm.Member = u.id AND u.Email LIKE '%@mail.ru')
WHERE
    u.Name IS NULL
спустя 9 минут [обр] Владимир Хоменко(2/67)[досье]
dacuan[досье] Это не будет правильно работать, потому что если в группе есть пользователь с Email = 'test@mail.com' и пользователь с Email = 'test@mail.ru', Ваш запрос выберет эту группу, тогда как по условию задачи не должен.
спустя 9 часов [обр] Закиров Руслан(12/343)[досье]

Самое лучшее, что я нашел:

SELECT
    g.id, g.Name
FROM
    Groups AS g, Users AS u
    LEFT JOIN GroupMembers AS gm on g.id = gm.Group AND gm.Member = u.id
WHERE
    u.Email = 'foo@mail.ru' AND gm.Member IS NULL

Работает только для случаев, когда условие по позьзователям возвращает одну запись. В остальных случаях полный провал и всё неправильно. Нужны либо подзапросы, либо группировки.

спустя 17 часов [обр] Дмитрий Попов(17/509)[досье]

А почему так принципиально отсутствие подзапросов или группировок (особенно группировок).

Религия?

спустя 41 минуту [обр] Закиров Руслан(12/343)[досье]
Нет, системные ограничения такие. Подзапросов нет из-за ограничений прослойки над базами, не дошли у нас руки встроить поддержку оных. Группировка с having пугает до ужаса :) Получается, что эти решения требуют дополнительных затрат на исследования и реализацию.
спустя 11 часов [обр] Дмитрий Попов(17/509)[досье]
Ну, having здесь по-моему не причем, насколько я понял задачу?
спустя 1 час 52 минуты [обр] Владимир Хоменко(2/67)[досье]

Дмитрий Попов[досье]Как раз таки причем.

Напишите выборку без having, буду очень сильно Вас уважать (-;

Закиров Руслан[досье]Честно говоря, не понимаю, что Вас так пугает в having, довольно стандартное средство. Я использую выборки с ним довольно давно и должен сказать, что никаких проблем никогда не было.

спустя 31 минуту [обр] Закиров Руслан(12/343)[досье]
Владимир Хоменко[досье] Немного пугают особенности реализации в mysql, там having выполняется после получения сета, а это черевато просто огромными проблемами с производительностью. Для нас лучше отложить эту проблему, до тех пор пока мы не найдем времени реализовать подзапросы.
Powered by POEM™ Engine Copyright © 2002-2005