5

次の表では、distinct を使用したいと思いますが、'PlayerID' 列でのみ使用します。これは私が現時点で持っているものです:

   MATCHID   PLAYERID     TEAMID MATCHDATE STARTDATE
---------- ---------- ---------- --------- ---------
        20          5          2 14-JAN-12 01-JUN-11
        20          5          4 14-JAN-12 01-JUN-10
        20          7          4 14-JAN-12 01-JUN-11
        20          7          2 14-JAN-12 01-JUN-10
        20         10          4 14-JAN-12 01-JUN-11
        20         11          2 14-JAN-12 01-JUN-10
        20         13          2 14-JAN-12 01-JUN-11
        20         16          4 14-JAN-12 01-JUN-10
        20         17          4 14-JAN-12 01-JUN-10
        20         18          4 14-JAN-12 01-JUN-10
        20         19          2 14-JAN-12 01-JUN-11

そして、これが私が望むものであり、各 'PlayerID' の最高の 'StartDate' が表示され、次の行は無視されます:

   MATCHID   PLAYERID     TEAMID MATCHDATE STARTDATE
---------- ---------- ---------- --------- ---------
        20          5          2 14-JAN-12 01-JUN-11
        20          7          4 14-JAN-12 01-JUN-11
        20         10          4 14-JAN-12 01-JUN-11
        20         11          2 14-JAN-12 01-JUN-10
        20         13          2 14-JAN-12 01-JUN-11
        20         16          4 14-JAN-12 01-JUN-10
        20         17          4 14-JAN-12 01-JUN-10
        20         18          4 14-JAN-12 01-JUN-10
        20         19          2 14-JAN-12 01-JUN-11

現在の SQL:

SELECT pi.MatchID, pi.PlayerID, t.TeamID, m.MatchDate, pf.StartDate
FROM Plays_In pi, Match m, Plays_A pa, Team t, Plays_For pf, Made_Up_Of muo, Season s
WHERE pi.MatchID = m.MatchID
AND m.MatchID = pa.MatchID
AND pa.TeamID = t.TeamID
AND pf.PlayerID = pi.PlayerID
AND pf.TeamID = t.TeamID
AND muo.MatchID = pi.MatchID
AND muo.SeasonID = s.SeasonID
AND pi.MatchID = '&match_id'
AND m.MatchDate >= pf.StartDate
ORDER BY pi.MatchID ASC, pi.PlayerID ASC, pf.StartDate DESC;

オラクルのデータベースです。

前もって感謝します。

4

3 に答える 3

8

数点...

  • 結合を使用して行を除外したり除外したりしない限りMade_Up_OfSeasonこれらのテーブルは必要ありません。ここでは省略しました。必要に応じて、それらを元に戻すことができます。

  • ANSI JOIN 構文を使用する必要があるという Mark Tickner の意見は正しいです。それについての良い点 (標準であること以外) は、結合されるテーブルに結合ロジックを正しく配置することです。慣れてきたらこちらの方がいいと思います。

  • あなたが本当に求めているのは、 pf.StartDateeach の最大値です。これは、分析関数PlayerIDにぴったりです。ROW_NUMBER()PARTITION BY pi.PlayerID ORDER BY pf.StartDate DESC基本的に、1各プレーヤーの最新の並べ替え日付の行に値を割り当てます。1外側は、ランキングのある行を除くすべての行を除外します。

  • RANK()および分析関数を使用してランキングを割り当てることもできますがDENSE_RANK()、プレーヤーが最新の日付で同点の場合、同点のすべての日付が 1 位にランク付けされ、そのプレーヤーについて複数の行が取得されます。プレーヤーごとに 1 つの行のみが必要なこのような状況では、ROW_NUMBER()代わりに を使用します。

すべてをまとめると、次のようになります。

SELECT MatchID, PlayerID, TeamID, MatchDte, StartDate FROM (
  SELECT
    pi.MatchID,
    pi.PlayerID,
    t.TeamID,
    m.MatchDate,
    pf.StartDate,
    ROW_NUMBER() OVER (PARTITION BY pi.PlayerID ORDER BY pf.StartDate DESC) AS StartDateRank
  FROM Plays_In pi
  INNER JOIN Match m ON pi.MatchID = m.MatchID
  INNER JOIN Plays_A pa ON m.MatchID = pa.MatchID
  INNER JOIN Team t ON pa.TeamID = t.TeamID
  INNER JOIN Plays_For pf ON pf.PlayerID = pi.PlayerID AND pf.TeamID = t.TeamID
  WHERE pi.MatchID = '&match_id'
  AND m.MatchDate >= pf.StartDate
)
WHERE StartDateRank = 1
ORDER BY MatchID, PlayerID

最後のポイント: に基づいて、 PHP をフロント エンドとして使用し、クエリを実行する関数をWHERE pi.MatchID = '&match_id'使用しているように見えます。mysqlもしそうなら、SQL インジェクションからあなたを守ってくれるので、代わりにmysqliorを調べてください。関数 (公式には非推奨) はそうではありませんPDOmysql


補遺: ROW_NUMBER@AndriyM に感謝します。

を使用ROW_NUMBERすると、プレーヤーに最新の日付の行が複数ある場合、行の 1 つだけが として割り当てられROW_NUMBER = 1、その行は多かれ少なかれランダムに選択されます。以下は、プレーヤーの最新の日付が 2013 年 5 月 1 日で、プレーヤーにこの日付の 3 つの行がある例です。

pi.MatchID  pi.PlayerID  pf.StartDate
----------  -----------  ------------
      100         1000   05/01/2013 <-- could be ROW_NUMBER = 1
      101         1000   04/29/2013
      105         1000   05/01/2013 <-- could be ROW_NUMBER = 1
      102         1000   05/01/2013 <-- could be ROW_NUMBER = 1 
      107         1000   04/18/2013

上記の行の1 つだけが割り当てられることに注意ROW_NUMBER = 1してください。あなたではなく、オラクルが決定します。

この不確実性が問題になる場合は、追加の列で並べ替えて、明確な勝者を取得します。この例ではpi.MatchID、「true」を決定するために最高値が使用されますROW_NUMBER = 1

-- replace `ROW_NUMBER...` in the query above with this:
    ROW_NUMBER() OVER (
      PARTITION BY pi.PlayerID
      ORDER BY pf.StartDate DESC, pi.MatchID DESC) AS StartDateRank

最高値が同点の場合pf.StartDate、Oracle は最高値pi.MatchID を持つ行のサブセット内でpf.StartDate最高値を探します。結局のところ、この条件を満たす行は 1 行だけです。

pi.MatchID  pi.PlayerID  pf.StartDate
----------  -----------  ------------
      100         1000   05/01/2013
      101         1000   04/29/2013
      105         1000   05/01/2013 <-- is ROW_NUMBER = 1: highest MatchID for
                                     -- most recent StartDate (5/1/2013)
      102         1000   05/01/2013
      107         1000   04/18/2013 <-- not considered: has the highest MatchID but isn't
                                     -- in the subset with the most recent StartDate
于 2013-05-03T02:31:40.283 に答える
0

たぶん使用してから使用をINTERSECT見つけますか?MAX(StartDate)GROUP BY

于 2013-05-03T02:10:43.533 に答える