05:46

# Exercise #(-2) page 2

Removing the "launched" column from grouping isn't enough to correct this mistake.

Console
Execute
`SELECT MIN(launched) FROM Ships aa, Classes bb WHERE bb.class = aa.class GROUP BY country;`
as a result we will get minimal years by every country:

1916
1913
1920

Then rows that satisfies predicate would look like this:

country x launched
Gt.Britain 6 1916
Japan 1 1913
Japan 1 1916
USA 1 1920

Thereby we have already lost correct rows for Japan and USA. We should take notice of this row for Japan:

Japan 1 1916
only by the reason that 1916th year concured with minimal year for USA. The following code doesn't have any sense. But it has mistake though. In the main query:

`SELECT country, MAX(x), MIN(launched) …GROUP BY country`
we have grouping by country with determining of two aggregated factors — maximum of ships’ quatities and minimum of years. Using of grouping in this case leads to mistake. Indeed, rows that we need could already be found in table which in the FROM clause (for instance {Gt.Britain, 6, 1916}). We do not need any grouping here, we only need to filter out wrong rows. As a result of grouping only one row will be remained. It have statistic rates for whole group. In this case the maximum and the minimum gain in different rows of the group. This is clearly visible at USA’s ships table. In this one minimal year does not correspond maximum value (x=1). The maximum value (x=3) is reached at 1941th year. That’s why such grouping may return right result only if all “x” values for country are equal.

Everything in this solution is reversed. Nevertheless let’s try to correct it by finding out the reasons of mistakes and delusions.

Correlated subquery is needed for binding of year and country. It can be used in WHERE clause (AND aa.country = s.country):

`WHERE launched = ANY(SELECT MIN(launched)  FROM Ships bb, Classes aa  WHERE aa.class = bb.class AND aa.country = s.country GROUP BY country )`

That is correct, but don’t take any effect for now, except maybe it excludes wrong row:

Japan 1 1916

For advance we need to calculate minimal year among ones with maximum quantity of ships for each contry. Maximum quantity of ships is primary here. If we would filter only by minimal year we can lose right rows. That’s why we need to count quantity of ships, not a minimal year:

`WHERE x >= ALL(SELECT COUNT(launched)  FROM Ships bb, Classes aa  WHERE bb.class = aa.class AND s.country=aa.country GROUP BY country, launched )`

Take a note at predicate >= ALL which gives us maximal value of “x”. Let’s rewrite whole query with taking into account all we have said about grouping in the main query.

Solution 3.6.2

Console
Execute
`SELECT country, x, launchedFROM (SELECT country, COUNT(*) x , launched  FROM Ships b, Classes a WHERE a.class = b.class  GROUP BY country, launched ) sWHERE x >= ALL(SELECT COUNT(launched)  FROM Ships bb, Classes aa  WHERE bb.class = aa.class AND s.country=aa.country GROUP BY country, launched );`

Is this all? Not at all. If maximum value would be gained in several different years the row for every such year will occur in the result. But we need to output the row with minimal year by the data. As it was noted above, this is the certain case when grouping is valid: all “x” values for country are equal and maximal.

 Pages 1 2 3 4