Oracle - SQL task.

----------------------------------------------------------------
(C) gRAVER_ZX, 2007
----------------------------------------------------------------

Oracle
SQL task

Task text.

For each country, determine the year when
the maximum was launched
the number of its ships.  In case
there will be several such years, take
the least of them.  Output: country, year,
number of ships.

The ship database is being considered,
participated in the Second World War.
There are the following relationships:

Classes (class, type, country, numGans, bore, displacement)
Ships (name, class, launched)

In fact, we will need it from the Classes table
only these fields: class, country.

In general, check your decisions on that
site where the condition of this was taken from
tasks, a very dubious pleasure.
It's better to create these two signs in
existing database and experiment with
with your requests to them as much as you like.
Moreover, the site gives an error:
this request:

SELECT country, launched, COUNT(name) c
FROM Classes, Ships
WHEREClasses.class=Ships.class
GROUP BY country, launched
ORDER BY country;

Oracle copes with it naturally.
So it’s better to experiment in that
environment from which you least expect
glitches.


Creating and filling tables.

CREATE TABLE classes(
  class VARCHAR2(16) NOT NULL,
  type VARCHAR2(2) NOT NULL,
  country VARCHAR2(16) NOT NULL,
  numguns NUMBER(2,0) NULL,
  bore NUMBER(2,0) NULL,
  displacement NUMBER(5,0) NULL
);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Bismarck','bb','Germany',8,15.0,42000);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Iowa','bb','USA',9,16.0,46000);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Kongo','bc','Japan',8,14.0,32000);

insert into classes
(class,type,country,numguns,bore,displacement) values ('North
Carolina','bb','USA',12,16.0,37000);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Renown','bc','Gt.Britain',6,15.0,32000);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Revenge','bb','Gt.Britain',8,15.0,29000);

insert into classes
(class,type,country,numguns,bore,displacement) values
('Tennessee','bb','USA',12,14.0,32000);

insert into classes(class,type,country,numguns,bore,displacement) values
('Yamato','bb','Japan',9,18.0,65000);

CREATE TABLE ships(
  name VARCHAR2(16) NOT NULL,
  class VARCHAR2(16) NOT NULL,
  launched NUMBER(5,0) NULL
);

insert into ships (name,class,launched) values
('California','Tennessee',1921);

insert into ships (name,class,launched) values
('Haruna','Kongo',1916);

insert into ships (name,class,launched) values ('Hiei','Kongo',
1914);

insert into ships (name,class,launched) values
('Iowa','Iowa',1943);

insert into ships (name,class,launched) values
('Kirishima','Kongo',1915);

insert into ships (name,class,launched) values
('Kongo','Kongo',1913);

insert into ships (name,class,launched) values
('Missouri','Iowa',1944);

insert into ships (name,class,launched) values
('Musashi','Yamato',1942);

insert into ships (name,class,launched) values ('New
Jersey','Iowa',1943);

insert into ships (name,class,launched) values ('North
Carolina','North Carolina',1941);

insert into ships (name,class,launched) values
('Ramillies','Revenge',1917);

insert into ships (name,class,launched) values
('Renown','Renown',1916);

insert into ships (name,class,launched) values
('Repulse','Renown',1916);

insert into ships (name,class,launched) values
('Resolution','Renown',1916);

insert into ships (name,class,launched) values
('Revenge','Revenge',1916);

insert into ships (name,class,launched) values ('Royal
Oak','Revenge',1916);

insert into ships (name,class,launched) values ('Royal
Sovereign','Revenge',1916);

insert into (ships,class,launched) values ('South
Dakota','North Carolina',1941);

insert into (name,class,launched) values
('Tennessee','Tennessee',1920);

insert into (name,class,launched) values
('Washington','North Carolina',1941);

insert into (name,class,launched) values
('Wisconsin','Iowa',1944);

insert into (name,class,launched) values
('Yamato','Yamato',1941);


Path to the solution.

Well, the first sketch.

SELECT country, launched, COUNT(*)
FROM classes, ships
GROUP BY country, launched
ORDER BY country;


hmm, a lot of lines are displayed.


***

so a country can produce several
classes of ships, as can be seen from
request:

SELECT country, class FROM classes ORDER BY country;


COUNTRY CLASS
---------------- ----------------
Germany Bismarck
Gt.Britain Revenge
Gt.Britain Renown
Japan Kongo
Japan Yamato
USA Tennessee
USA Iowa
USA North Carolina

8 rows selected.


***

it turns out that COUNTRY---SELECT country, launched, name, classes.class
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched
ORDER BY country, launched;

number of ships launched for each
year, for each country.


***

SELECT country, launched, COUNT(*)
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched
ORDER BY country, launched
HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes, ships
WHERE classes.class=ships.class
GROUP by country, launched);


HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes, ships
*
error on line 6:
ORA-00933: invalid SQL statement termination

well, it’s clear that HAVING comes before ORDER,
which is confirmed further.


***

SELECT country, launched, COUNT(*)
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched
HAVING COUNT(*)>=2


COUNTRY LAUNCHED COUNT(NAME)
---------------- ---------- -----------
USA 1943 2
USA 1941 3
USA 1944 2
Gt.Britain 1916 6


***

SELECT country, launched, COUNT(*)
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched
HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROMclasses, ships
WHERE classes.class=ships.class
GROUP by country, launched);


COUNTRY          LAUNCHED   COUNT(*)
---------------- ---------- ----------
Gt.Britain       1916       6

дело  в том, что подзапрос в HAVING выдает
значения  по  всем странам, а нужно только
по конкретной.


***

SELECT *
FROM (SELECT country, launched, COUNT(*) c
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched)
WHERE c>=ALL(SELECT COUNT(*) FROM classes, ships
WHERE classes.class=ships.class
GROUP by country, launched);


строки не выбраны

что-то такая мысль ни к чему не привела.


***!!!***

SELECT country, launched, COUNT(*)
FROM classes c1, ships
WHERE c1.class=ships.class
GROUP BY country, launched
HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes c2, ships
WHERE c2.class=ships.class AND c1.country=c2.country
GROUP by country, launched)
ORDER BY country;

итак  я  нашел  года  для  каждой  стран с
максимальным  количеством спусков кораблей
на воду:


COUNTRY          LAUNCHED   COUNT(*)
---------------- ---------- ----------
Gt.Britain       1916       6
Japan            1914       1
Japan            1915       1
Japan            1941       1
Japan            1942       1
Japan            1913       1
Japan            19161
USA              1941       3

8 строк выбрано.


***

SELECT *
FROM (SELECT country, launched, COUNT(*) c
FROM classes, ships
WHERE classes.class=ships.class
GROUP BY country, launched) c1
WHERE c>=ALL(SELECT COUNT(*) FROM classes c2, ships
WHERE c2.class=ships.class AND c1.country=c2.country
GROUP by country, launched);


строки не выбраны

опять  не  получилось.  я уж не помню чего
хотел-то здесь.


***

SELECT country, launched, COUNT(*)
FROM classes c1, ships
WHERE c1.class=ships.class
GROUP BY country, launched
HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes c2, ships
  WHERE c2.class=ships.class AND c1.country=c2.country
  GROUP by country, launched)
AND launched<=ALL(SELECT launched FROM classes c2, ships
  WHERE c2.class=ships.class AND c1.country=c2.country
  GROUP by country, launched)
ORDER BY country;


COUNTRY          LAUNCHED   COUNT(*)
---------------- ---------- ----------
Gt.Britain       1916       6
Japan            1913       1


***

отталкиваясь от ***!!!*** получаю

SELECT * FROM
(
SELECT country, launched, COUNT(*)
FROM classes c1, ships
WHERE c1.class=ships.class
GROUP BY country, launched
HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes c2, ships
  WHERE c2.class=ships.class ANDc1.country=c2.country
  GROUP by country, launched)
ORDER BY country
) l1
WHERE launched<=ALL(SELECT launched FROM(
  SELECT country, launched, COUNT(*)
  FROM classes c1, ships
  WHERE c1.class=ships.class
  GROUP BY country, launched
  HAVING COUNT(*)>=ALL(SELECT COUNT(*) FROM classes c2, ships
  WHERE c2.class=ships.class AND c1.country=c2.country
  GROUP by country, launched)
  ORDER BY country
  ) l2
  WHERE l1.country=l2.country);


COUNTRY          LAUNCHED   COUNT(*)
---------------- ---------- ----------
Gt.Britain       1916       6
Japan            1913       1
USA              1941       3

что и требовалось найти : )))

Share your thoughts about the article