2016-03-18 7 views
2

私は、次のバレーボールの試合がいつ起こるかを知る必要があります。私は、結果がIS NULLであるため、まだ起こっていないすべてのバレーボールの試合に、試合の日程をうまく絞り込んだ。私はすべての行を選択している、私はちょうど最も早い日付を見つける必要があります。ここで最新の日付または最も早い日付を検索する<code>team_ID</code>という外部キー、<code>game_date</code>という日付の列、<code>result</code>という1つのcharの列を持つテーブルがあります。

は、私が持っているものです:私は、時間旅行者だ

SELECT game.game_date, team.team_name 
FROM game 
JOIN team 
ON team.team_id = game.team_id 
WHERE team.sport_id IN 
    (SELECT sport.sport_id 
    FROM sport 
    WHERE UPPER(sport.sport_type_code) IN 
     (SELECT UPPER(sport_type.sport_type_code) 
     FROM sport_type 
     WHERE UPPER(sport_type_name) like UPPER('%VOLLEYBALL%') 
     ) 
    ) 
AND game.result IS NULL; 

をので、古い日付を気にしません。

私はそれを実行すると、私はこれを取得:

GAME_DATE TEAM_NAME 
----------- ---------- 
11-NOV-1998 BEars 
13-NOV-1998 BEars 
13-NOV-1998 WildCats 
14-NOV-1998 BEars 

私はので、私はその日に演奏のみMIN(DATE)TEAM_NAMEを取得し、それを設定するにはどうすればよいですか?

私はAND game.game_date = MIN(game.game_date)を試しましたが、ここではグループ機能が許可されていないことを伝えています。 MIN(game_date)を取得し、それを満たす条件として使用する方法がなければなりません。

私はOracle 11g pl/sqlを使用しています。

Game ERD

これは、最終的な作業コードでなければなりません。

SELECT * 
    FROM 
    (
    SELECT g.game_date, t.team_name 
     FROM game g 
     JOIN team t 
     ON t.team_id = g.team_id 
     JOIN sport s 
     ON t.sport_id = s.sport_id 
     JOIN sport_type st 
     ON UPPER(s.sport_type_code) IN UPPER(st.sport_type_code) 
    WHERE UPPER(sport_type_name) like UPPER('%VOLLEYBALL%') 
     AND g.result IS NULL 
    ORDER BY g.game_date 
    ) 
WHERE ROWNUM = 1; 
+0

こと'ORDER BY'節が適用される前に' ROWNUM' psuedocolumnが生成されるので、 "final"コードは動作するとは保証されません。データベースが行を生成して残りを破棄し、データ。データベースが偶然最小の行を最初に生成しているので動作しているように見えますが、動作することは保証されていません(ほとんどの場合、動作しません)。 – MT0

答えて

3

ORDER BY句がクエリに適用される前に、ROWNUM疑似列が生成されます。 WHERE ROWNUM <= Xを実行すると、Xの行は、Oracleがデータファイルから作成する順序に関係なく、最小行ではなく、Xとなります。あなたはORDER BYが最初に使用し、このようなROWNUMにフィルタリングするために必要な最小限の行を取得して保証するために:あなたは、最小日付で複数の行を返すようにしたい場合は

SELECT * 
FROM (
    SELECT g.game_date, t.team_name 
    FROM game g 
     JOIN team t 
     ON t.team_id = g.team_id 
     INNER JOIN sport s 
     ON t.sport_id = s.sport_id 
     INNER JOIN sport_type y 
     ON UPPER(s.sport_type_code) = UPPER(y.sport_type_code) 
    WHERE UPPER(y.sport_type_name) LIKE UPPER('%VOLLEYBALL%') 
    AND g.result IS NULL 
    ORDER BY game_date ASC -- You need to do the ORDER BY in an inner query 
) 
WHERE ROWNUM = 1; -- Then filter on ROWNUM in an outer query. 

SELECT game_date, 
     team_name 
FROM (
    SELECT g.game_date, 
     t.team_name, 
     RANK() OVER (ORDER BY g.game_date ASC) AS rnk 
    FROM game g 
     JOIN team t 
     ON t.team_id = g.team_id 
     INNER JOIN sport s 
     ON t.sport_id = s.sport_id 
     INNER JOIN sport_type y 
     ON UPPER(s.sport_type_code) = UPPER(y.sport_type_code) 
    WHERE UPPER(y.sport_type_name) LIKE UPPER('%VOLLEYBALL%') 
    AND g.result IS NULL 
) 
WHERE rnk = 1; 
+0

'rank()'の目的を説明できますか?また、あなたが使用した「上書き」機能について語るオンラインリソースはありません。 –

+0

['RANK'](https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions123.htm)は行をランク付けします(' ROWNUM'を適用するのと同様ですが)複数の行が等しい値を持つ場合( 'ORDER BY'節に基づいて)、それらは同じランクを有する(一方、ROWNUMは、それらが等しい値を有するか否かにかかわらず、各行にシーケンスの次の番号を与える)。あなたは、2人の競技者が同じレースで同じ時間を持っているかのように、同じ表彰台の場所を共有するかのように考えるか、ランク付けすることができます。 – MT0

+0

私は最終的にあなたが記述したものを使用して作業コードを得ました。 –

0

日付とSELECT TOP 1で簡単に並べ替えることができますか?私はこれがOracleの構文だと思う:

WHERE ROWNUM < = number;

+0

これで問題が解決します。サイトでは、あなたを答えとしてマークするつもりですが、「MIN」や「MAX」関数から取得した値を満たす条件として具体的に質問する別の質問をするつもりです'WHERE COLUMN = MIN(COLUMN)'で指定します。 –

+1

'ROWNUM <= X'を' WHERE'節に追加するのは簡単ではありません。 'ROWNUM'疑似列は、' ORDER BY'節がクエリに適用される前に生成されるからです。 'WHERE ROWNUM <= X'を実行すると、Oracleがデータファイルからデータを生成する順番どおりに' X'行が取得され、 'X'最小行は取得されません(OPの例では、これが保証されていない場合には動作するように見えます)。 – MT0

+0

その場合は、次のように読んでください。http://stackoverflow.com/questions/11978136/how-can-i-get-just-the-first-row-in-a-result-set-after-オーダー –

0
select game.game_date,team.team_name from (
SELECT game.game_date, team.team_name, rank() over (partition by team.team_name order by game.game_date asc) T 
FROM game 
JOIN team 
ON team.team_id = game.team_id 
WHERE team.sport_id IN 
    (SELECT sport.sport_id 
    FROM sport 
    WHERE UPPER(sport.sport_type_code) IN 
     (SELECT UPPER(sport_type.sport_type_code) 
     FROM sport_type 
     WHERE UPPER(sport_type_name) like UPPER('%VOLLEYBALL%') 
     ) 
    ) 
AND game.result IS NULL 
) query1 where query1.T=1; 
関連する問題