2

テーブル:

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

質問:

各クラスについて、戦闘で沈没したそのクラスの船の数を見つけてください。

私の答え:

  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テーブルを含めなければならなかったのかということです.私のクエリは十分ではありませんか? 私は同じことをしていますが、classesテーブルに参加していません。前もって感謝します。

4

9 に答える 9

2

最も単純な答え...

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
于 2016-09-18T11:02:30.873 に答える
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;
于 2013-03-10T18:19:18.320 に答える
1

それは非常に近かったので、私はKaczmarskiに投票します。機能する答えには、2回目のパスでエラーチェックに合格するための追加の行が1つあります。

ships.nameにクラス名でもある名前が含まれていないことを確認するためのチェックが必要です。

効率的なデータベース構造には、ビスマルクと沈没したすべての船が結果テーブルと船のテーブルに含まれます。または、ships テーブルには沈没した船がまったく含まれていません。

このタイプの方法は、データベースが複数のユーザーによって変更されており、ユーザーが変更されているテーブルへの読み取りアクセス権を持っている現実のシナリオで使用する必要があります。

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
于 2015-11-25T17:32:04.407 に答える
0

これは、あなたの TA (ティーチング アシスタント?) に尋ねるのに良い質問です。あなたの本の中の答えが使われたのには、「教える」理由があるかもしれません。

あなたのクエリと本からのクエリは同じ結果を生成しますが、「クラス」に関する他の質問に答えるためにクエリを簡単に変更することはできません。たとえば、質問が「各国で沈没した船の数は?」に変わったとします。「本のクエリ」を簡単に変更するだけで、それが簡単になります (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句としてクエリを開始し、必要に応じて関連する他のテーブルに結合します。これにより、少なくともコードが読みやすくなります。

于 2013-03-10T18:54:37.957 に答える
0

両方のクエリに実際の違いはありません。group by と count を select から削除すると、違いが生じる可能性があります。異なるクラスに複数の同じ船名が存在する可能性があるためです。クラスごとにグループを使用しているため、両方のクエリで違いはありません。どちらのクエリでも、クラスごとの船舶数が返されます。

于 2013-03-10T18:27:48.557 に答える
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
于 2015-08-24T15:23:23.153 に答える