web-dev-qa-db-ja.com

複数の左結合またはサブクエリ?

複数のテーブルを結合してユーザーの「実行」に関連するいくつかのデータを抽出する作業をしています。これには、runID、ユーザー名などの基本が含まれますが、実行時間やお気に入りにも結合されます。

以下のクエリでは、LEFT JOINおよびuser_run_timesテーブルにrun_favouritesを使用しています。

クエリは、ユーザーのすべての実行、お気に入りの場合は最後に実行された日付、および最速の実行時間を表示する必要があります-そのすべてが表示されますが、複数回ログに記録された場合、お気に入りの数は1を超えます1または0)。

SELECT
    user_runs.userID,
    user_runs.runID,
    `createdBy`,
    `username`,
    DATE_FORMAT(`dateCreated`,'%d-%m-%Y') `dateCreated`, 
    COUNT(runFavouriteID) AS favourite,
    DATE_FORMAT(MAX(`runDate`),'%d-%m-%Y') AS `lastRan`,
    MIN(`runTime`) AS `fastestTime`
FROM
    `user_runs` 
    INNER JOIN `runs` ON user_runs.runID = runs.runID
    INNER JOIN `users` ON users.userID = runs.createdBy
    LEFT OUTER JOIN `user_run_times` ON user_run_times.runID = user_runs.runID 
    LEFT OUTER JOIN `run_favourites` ON run_favourites.runID = user_runs.runID
WHERE
    user_runs.userID = 4
GROUP BY
    runID, user_run_times.runID;

このクエリを改善する方法に関するいくつかの提案を探していますか?現在の出力は次のとおりです。

UserID   runID    createdBy   username   dateCreated   favourite   lastRan       fastestTime
4        3        3           bob        11-12-2011    3           27-01-2012    36920030

favouriteは1つだけを表示する必要があります(run_favouritesには行が1つあるため)が、3つ表示されます(user_run_timesに2つ、run_favouritesに1つ)。

うまくいけば、私はこれをあまり混乱させていません。誰かが私がここで最も多くのように「テキスト」形式でテーブル構造を出力する方法を提案できたら、それらも投稿します。

どんなアドバイスでも感謝します、ありがとう! :)

4
Elliott

これは、テーブル構造を見ることのない私のベストショットです

SELECT
    user_runs.userID,
    user_runs.runID,
    `createdBy`,
    `username`,
    DATE_FORMAT(`dateCreated`,'%d-%m-%Y') `dateCreated`, 
    COUNT(DISTINCT runFavouriteID) AS favourite,
    DATE_FORMAT(MAX(`runDate`),'%d-%m-%Y') AS `lastRan`,
    MIN(`runTime`) AS `fastestTime`
FROM
    (SELECT * FROM `user_runs` WHERE userID=4) user_runs
    INNER JOIN `runs` ON user_runs.runID = runs.runID
    INNER JOIN `users` ON users.userID = runs.createdBy
    LEFT OUTER JOIN `user_run_times` ON user_run_times.runID = user_runs.runID 
    LEFT OUTER JOIN `run_favourites` ON run_favourites.runID = user_runs.runID
GROUP BY
    user_runs.runID,`createdBy`,`username`,`dateCreated`;

これらのインデックスが必要になります

ALTER TABLE user_runs ADD INDEX userID_runID_ndx (userID,runID);
ALTER TABLE runs      ADD INDEX runID_createdBy_ndx (runID,createdBy);
ALTER TABLE runs      ADD INDEX createdBy_runID_ndx (createdBy,runID);
3
RolandoMySQLDBA