в результате чего будут получены минимальные годы по каждой стране:
1916
1913
1920
Тогда строки, удовлетворяющие предикату, будут выглядеть так:
country
x
launched
Gt.Britain
6
1916
Japan
1
1913
Japan
1
1916
USA
1
1920
Таким образом, мы уже потеряли правильные строки для Японии и США. Следует обратить внимание еще и на то, что мы получили строку для Японии:
Japan
1
1916
только на основании того, что год 1916 совпал с минимальным годом для США. Дальнейший код не имеет смысла. Однако и там имеется принципиальная ошибка. В основном запросе
SELECT country, MAX(x), MIN(launched)
…
GROUPBY country
выполняется группировка по стране с определением двух агрегатных показателей — максимума по количеству кораблей и минимума по году. Использование в данном случае группировки ошибочно. Действительно, нужные нам строки уже находятся в таблице, получаемой в предложении FROM (например, строка {Gt.Britain, 6, 1916}). Зачем же здесь группировка, когда требуется лишь критерий, который поставит фильтр, отсекающий лишние строки. В результате же группировки образуется одна строка, содержащая статистические показатели для всей группы. При этом максимум и минимум в общем случае достигаются в разных строках группы. Это хорошо видно из таблицы на примере кораблей США, когда минимальному году отвечает далеко не максимальное значение (x=1), а максимальное значение (x=3) достигается совсем в другом году (1941). Поэтому такая группировка может дать правильный результат (в смысле условия задачи) только в том случае, если все значения x для страны совпадают.
Все в этом решении поставлено с ног на голову. Тем не менее, выяснив причины ошибок и заблуждений, попытаемся исправить его без радикальной переработки.
Чтобы все же связать год со страной, можно использовать коррелирующий подзапрос в предложении WHERE (AND aa.country = s.country):
WHERE launched = ANY(SELECTMIN(launched)
FROM Ships bb, Classes aa
WHERE aa.class = bb.class AND
aa.country = s.country
GROUPBY country
)
Это правильно, но пока ничего не меняет, разве что исключит неправильную строку:
Japan
1
1916
Чтобы двигаться дальше, нужно вычислять минимальный год среди лет с максимальным количеством кораблей для каждой страны. Здесь первичным является максимальное количество кораблей. Ведь выбирая лишь минимальный год, мы можем потерять правильные строки. Поэтому в предикате нужно оценивать не год, а количество кораблей:
WHERE x >= ALL(SELECTCOUNT(launched)
FROM Ships bb, Classes aa
WHERE bb.class = aa.class AND
s.country=aa.country
GROUPBY country, launched
)
Обратите внимание на предикат >= ALL — (больше или равно), который дает нам максимальное значение x. Перепишем весь запрос с учетом сказанного о группировке в основном запросе:
Все? Не совсем. Если максимум для какой-нибудь страны достигается в разные годы, то мы получим по строке на каждый год. Нам же по условиям задачи требуется в таком случае вывести минимальный год. Как было отмечено выше, это как раз тот самый случай, когда группировка приемлема по смыслу (все значения x для страны одинаковы — максимальны):