2013-03-10 3 views
1

Таблицы:SQL пример запроса (мой ответ правильный?)

  • Classes (class, type, country, numGuns, bore, displacement)
  • Ships (name, class, launched)
  • Outcome (ship, battle, result)

Вопрос:

Найти для каждого класса номера кораблей этого класса t затонул в битве.

Мой ответ:

SELECT ships.class, COUNT(*) 
    FROM ships, outcome 
    WHERE ships.name = outcomes.ship AND outcome.result = 'sunk' 
    GROUP BY ships.class 

Ответ с присоединиться:

SELECT class, COUNT(*) 
    from ships 
    inner join outcomes 
    on name = ship 
    where outcome.result = 'sunk' 
    group by class 

Ответ дал в образце буклете:

SELECT classes.class, COUNT(*) 
    FROM classes, ships, outcomes 
    WHERE classes.class = ships.class AND ship = name AND result = 'sunk' 
    GROUP BY classes.class; 

То, что я не получаю почему они должны включать таблицу classes, не мой запрос su fficient? Я делаю то же самое, но не присоединяюсь к таблице classes. Заранее спасибо.

+4

Что это «Вводная брошюра» вы читаете, что есть SQL-запросов с синтаксисом, истекает 20 лет? – RBarryYoung

+0

Ваш запрос верный, но его можно улучшить, присоединившись к вашим таблицам –

+0

@RBarryYoung Dunno Я получил ответы на вопросы в Интернете. Это некоторые слайды ТА. Не упоминается о дате. – user1071840

ответ

2

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

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


Стоит также отметить, что этот синтаксис:

SELECT classes.class, COUNT(*) 
FROM classes, ships, outcomes 
WHERE classes.class = ships.class AND ship = name AND result = 'sunk' 
GROUP BY classes.class; 

архаичен и устаревшим. Это предпочтительный современный синтаксис:

SELECT classes.class, COUNT(*) 
FROM classes 
INNER JOIN ships ON classes.class = ships.class 
INNER JOIN outcomes ON outcomes.ship = ships.name 
WHERE outcomes.result = 'sunk' 
GROUP BY classes.class; 
+0

Смысл, синтаксис (старомодный) equi-join ('WHERE tableA.fk = tableB.pk') всегда выполняет' OUTER JOIN'? – stakx

+0

@stakx Нет, старый синтаксис выполнял бы внутреннее соединение, если использовался '=' или внешнее объединение, если использовались '= *' или '* ='. – RBarryYoung

+0

@stakx Упс, я понимаю, что вы имели в виду. Нет моего первоначального ответа неверно. Я исправлю ... – RBarryYoung

0

В обоих запросах нет никакой реальной разницы. Там может быть разница, если вы удаляете группу по и подсчитываете выбор. Потому что в разных классах может быть несколько одинаковых имен кораблей. Поскольку вы используете группу по классам, это не имеет никакого значения в обоих запросах. Оба запроса возвращают количество судов в классе.

0

Это был бы хороший вопрос, чтобы спросить своего ТП (помощника по обучению?). Могут быть «объяснения» причин, по которым был использован ответ в вашей книге.

Хотя ваш запрос и один из книги приведут к такому же результату, ваш запрос не может быть легко изменен, чтобы отвечать на другие вопросы о «классах». Например, предположим, что вопрос меняется на «Сколько кораблей было затоплено для каждой страны?». Простое изменение в «книге запрос» делает это легко (с помощью переформатировать код RBarryYoung в):

SELECT classes.country, COUNT(*) 
FROM classes 
INNER JOIN ships ON classes.class = ships.class 
INNER JOIN outcomes ON outcomes.ship = ships.name 
WHERE outcomes.result = 'sunk' 
GROUP BY classes.country; 

Это может быть тонким моментом, но начать запросы с таблицей вы «больше всего интересует», как FROM, а затем при необходимости присоединитесь к другим связанным таблицам. Это, по крайней мере, делает ваш код более легким для чтения.

0

Ваш запрос не перечислите все классы только те, где лодки потоплены это немного лучше, но, кажется, до сих пор неправильно:

select class, sum(sunks) as sunks from(
    select class, sum(case result when 'sunk' then 1 else 0 end) as sunks 
    from classes c left join outcomes o on c.class = o.ship 
    group by class 
    union all 
    select class, sum(case result when 'sunk' then 1 else 0 end) as sunks 
    from ships s left join outcomes o on s.name = o.ship 
    group by class 
)as x 
group by class 
1

Я бы голосовать до Kaczmarski, как это было очень близко. Ответ, который работает, имеет одну дополнительную строку для передачи проверки на второй проход.

Должна быть проверка, чтобы убедиться, что ships.name не содержит имени, которое также является именем класса.

Эффективная структура базы данных будет включать в себя Бисмарк и все корабли, которые были погружены в таблицу результатов, а также в таблицу кораблей. Или в таблице кораблей не было бы ни одного корабля, который был потоплен.

Этот тип метода должен использоваться в сценарии реального мира, в котором база данных изменяется несколькими пользователями, и пользователь имеет доступ на чтение к изменяющейся таблице.

select class, sum(sunks) as sunks from(
    select class, sum(case result when 'sunk' then 1 else 0 end) as sunks 
    from classes c left join outcomes o on c.class = o.ship 
where class not in (select name from ships) 
    group by class 
    union all 
    select class, sum(case result when 'sunk' then 1 else 0 end) as sunks 
    from ships s left join outcomes o on s.name = o.ship 
    group by class 
)as x 

group by class 
+0

Добро пожаловать в переполнение стека. Ваш ответ трудно подготовить. Рассмотрите возможность его редактирования и правильного форматирования. –

1

Более эффективный подход будет:

select class, SUM(CASE WHEN result='sunk' 
      THEN 1 
      ELSE 0 END) from 
(
select class,ship as name,result from classes cc left outer join outcomes oo ON cc.class=oo.ship 
union 
select class,name,result from ships ss left outer join outcomes oo ON ss.name=oo.ship 
) as ttt 
group by class 
0

Самый простой ответ ...

SELECT class, 
SUM(CASE WHEN result='sunk' THEN 1 ELSE 0 END) 
FROM 
(
    SELECT class, ship, result 
    FROM Classes c 
    LEFT JOIN Outcomes o 
    ON o.ship=c.class 
UNION 
    SELECT class, ship, result 
    FROM Ships s 
    LEFT JOIN Outcomes o 
    ON o.ship=s.class OR o.ship=s.name 
) 
AS res 
GROUP BY class 
Смежные вопросы