Ответ 1
Семантика наличия
Чтобы лучше понять, нужно ли это видеть с теоретической точки зрения.
A группа - это запрос, который берет таблицу и суммирует ее в другой таблице. Вы суммируете исходную таблицу, группируя исходную таблицу в подмножества (на основе атрибутов, которые вы указали в группе). Каждая из этих групп даст один кортеж.
Имея, просто эквивалентно предложению WHERE после, группа выполнила и до того, как вычисляется часть запроса select.
Допустим, что ваш запрос:
select a, b, count(*)
from Table
where c > 100
group by a, b
having count(*) > 10;
Оценить этот запрос можно следующим образом:
- Выполните WHERE, исключив строки, которые не удовлетворяют этому.
- Группировать таблицу в подмножества, основанные на значениях a и b (каждый кортеж в каждом подмножестве имеет те же значения a и b).
- Устранить подмножества, не удовлетворяющие условию HAVING
- Обработка каждого подмножества, выводящего значения, как указано в части SELECT запроса. Это создает один выходной набор на подмножество, оставшееся после шага 3.
Вы можете расширить это на любой сложный запрос. Таблица может представлять собой любой сложный запрос, возвращающий таблицу (кросс-продукт, соединение, UNION и т.д.).
Фактически имеет синтаксический сахар и не увеличивает возможности SQL. Любой заданный запрос:
SELECT list
FROM table
GROUP BY attrList
HAVING condition;
можно переписать как:
SELECT list from (
SELECT listatt
FROM table
GROUP BY attrList) as Name
WHERE condition;
Listatt - это список, который включает атрибуты GROUP BY и выражения, используемые в списке и состоянии. Может потребоваться назвать некоторые выражения в этом списке (с AS). Например, приведенный выше пример запроса можно переписать как:
select a, b, count
from (select a, b, count(*) as count
from Table
where c > 100
group by a, b) as someName
where count > 10;
Требуемое решение
Ваше решение кажется правильным:
SELECT s.sid, s.name
FROM Supplier s, Supplies su, Project pr
WHERE s.sid = su.sid AND su.jid = pr.jid
GROUP BY s.sid, s.name
HAVING COUNT (DISTINCT pr.jid) >= 2
Вы присоединяетесь к трем таблицам, а затем используете sid в качестве атрибута группировки (sname функционально зависит от него, поэтому он не влияет на количество групп, но вы должны включать его, в противном случае он не может быть частью выбранной части заявления). Затем вы удаляете те, которые не удовлетворяют вашему условию: удовлетворяют pr.jid is >= 2
, которые вы хотели первоначально.
Лучшее решение вашей проблемы
Я лично предпочитаю более простое решение для очистки:
- Вам нужно группировать только товары (sid, pid, jid **, количество), чтобы найти сид из тех, которые поставляют по меньшей мере два проекта.
- Затем присоедините его к таблице поставщиков, чтобы получить тот же поставщик.
SELECT sid, sname from
(SELECT sid from supplies
GROUP BY sid, pid
HAVING count(DISTINCT jid) >= 2
) AS T1
NATURAL JOIN
Supliers;
Он также будет выполняться быстрее, потому что соединение выполняется только тогда, когда это необходимо, не все время.
- DMG