2

Here is a schema about battleships and the battles they fought in:

 Ships(name, yearLaunched, country, numGuns, gunSize, displacement)
 Battles(ship, battleName, result)

A typical Ships tuple would be:

 ('New Jersey', 1943, 'USA', 9, 16, 46000)

which means that the battleship New Jersey was launched in 1943; it belonged to the USA, carried 9 guns of size 16-inch (bore, or inside diameter of the barrel), and weighted (displaced, in nautical terms) 46,000 tons. A typical tuple for Battles is:

 ('Hood', 'North Atlantic', 'sunk')

That is, H.M.S. Hood was sunk in the battle of the North Atlantic. The other possible results are 'ok' and 'damaged'

Question: List all the pairs of countries that fought each other in battles. List each pair only once, and list them with the country that comes first in alphabetical order first

Answer: I wrote this:

SELECT 
    a.country, b.country 
FROM 
    ships a, ships b, battles b1, battles b2 
WHERE 
    name = ship 
    and b1.battleName = b2.battleName 
    and a.country > b.country

But it says ambiguous column name. How do I resolve it? Thanks in advance

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
clever_bassi
  • 2,392
  • 2
  • 24
  • 43
  • 3
    well, `name = ship` is the problem. name could be from a or b, and ship from b1 or b2 – Raphaël Althaus Oct 03 '13 at 22:31
  • In your WHERE clause, `name=ship` needs to qualified. Also, how can you distinguish between opposing contries in a battle and allied countries in the same battle? – RBarryYoung Oct 03 '13 at 22:32
  • SQL doesn't know which name and ship you're looking for.. try: `SELECT a.country, b.country from ships a, ships b, battles b1, battles b2 WHERE a.name=b1.ship and b1.battleName=b2.battleName and a.country>b.country` – Mohamed Nuur Oct 03 '13 at 22:36

3 Answers3

4

Well, name = ship is the problem. name could be from a or b, and ship from b1 or b2

you could do something like that :

select distinct s1.country, s2.country
from ships s1
inner join Battles b1 on b.ship = s1.name
inner join Battles b2 on b2.ship <> s1.name and b2.battleName = b1.battleName
inner join ships s2 on s2.name = b2.ship and s2.country < s1.country
Raphaël Althaus
  • 59,727
  • 6
  • 96
  • 122
1

Could you try a nested query getting a table of winners and losers and then joining them on the battle name?

SELECT
WINNER.country as Country1
,LOSER.country as Country2

FROM
(
  SELECT DISTINCT country, battleName
  FROM Battles 
  INNER JOIN Ships ON Battles.ship = Ships.name
  WHERE Battles.Result = 1
) AS WINNER

INNER JOIN 
(
  SELECT DISTINCT country, battleName
  FROM Battles 
  INNER JOIN Ships ON Battles.ship = Ships.name
  WHERE Battles.Result = 0
) AS LOSER

ON WINNER.battlename = LOSER.battlename
ORDER BY WINNER.country
JustinHui
  • 729
  • 5
  • 18
0

try this, i think it's concise:

SELECT DISTINCT s1.country, s2.country
FROM ships s1, ships s2, battles b1, battles b2 -- i just list all tables here but you can use the left join etc.
WHERE s1.name=b1.ship AND s2.name=b2.ship AND b1.battleName=b2.battleName -- for the tables to join each other
AND s1.country < s2.country --key condition
ORDER BY s1.country ASC