web-dev-qa-db-fra.com

Plusieurs jointures de gauche ou sous-requête?

Je travaille pour rejoindre plusieurs tables ensemble pour extraire des données relatives à l'utilisateur "Runs", cela inclut des bases telles que Runid, Nom d'utilisateur, etc., mais rejoint également les heures d'exécution et les favoris.

J'ai la requête ci-dessous qui utilise un LEFT JOIN pour le user_run_times et run_favourites tableau.

La requête doit afficher toutes les exécutions pour l'utilisateur, la date de date la plus récente, si c'est un favori et le temps d'exécution le plus rapide - tout ce qui est affiché, mais si plusieurs fois sont enregistrés, le nombre de favoris va au-dessus d'un (devrait seulement être un ou zéro).

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;

Je cherche quelques suggestions sur la manière d'améliorer cette requête? La sortie actuelle est la suivante:

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

La colonne favourite doit seulement afficher un (comme il y a une ligne en run_favourites) Mais cela montre trois (deux pour user_run_times et un pour run_favourites)

J'espère que je n'ai pas fait cela trop déroutant, si quelqu'un pouvait suggérer comment je peux produire la structure de la table dans un format "texte" comme le plus important ici, je posterai également ceux-ci.

Tout conseil apprécié, merci! :)

4
Elliott

C'est mon meilleur coup sans voir des structures de table

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`;

Vous aurez besoin de ces index

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