2
votes

Rejoignez Tricky Triple Sql en recherchant la date la plus récente

Je m'excuse si cette question a déjà été posée de la même manière. Je suis plutôt nouveau dans SQL et j'ai beaucoup de mal à trouver la solution à mon problème. Très confus.

J'ai actuellement trois tableaux:


Modèles - | id | nom |


Utilisateurs - | id | full_name |


Journal des modifications - | id | id_user | id_template | last_edited_at


J'ai un tableau rempli de modèles.

J'ai un tableau séparé plein d'utilisateurs QUI apportent des modifications à ces modèles. Chaque fois qu'une modification est apportée, une entrée est créée dans la table du journal des modifications.

J'essaie de créer une requête dont l'objectif principal est de récupérer CHAQUE enregistrement à partir des modèles, ainsi que QUAND il a été modifié le plus récemment , et PAR QUI.

J'ai créé cette requête qui me permet de trouver la modification la plus récente pour un ID de modèle spécifique.

SELECT changelogs.id_user, changelogs.updated_at, users.full_name
FROM changelogs
JOIN users
ON changelogs.id_user = users.id
WHERE changelogs.id_template = :templateId
ORDER BY changelogs.updated_at DESC 
LIMIT 1

Je a essayé de résoudre ce problème en parcourant chaque enregistrement de modèle et en exécutant la requête ci-dessus pour chaque ID d'enregistrement, mais cela est lent et ne fonctionne pas. Je sais qu'il doit y avoir un moyen de faire cela en SQL, et je voulais voir si quelqu'un a résolu un problème similaire. Je n'ai pas conçu cette base de données, donc désolé si elle n'est pas optimisée.

Mon résultat final idéal serait une table qui ressemblerait à:


| template.id | template.name | user.name | changelog.updated_at |

Merci d'avance pour vos conseils


0 commentaires

3 Réponses :


0
votes

Vous pouvez utiliser une sous-requête corrélée:

SELECT cl.id_user, cl.updated_at, u.full_name
FROM changelogs cl JOIN
     users u
     ON cl.id_user = u.id
WHERE cl.updated_at = (SELECT MAX(cl2.updated_at)
                       FROM changelogs cl2
                       WHERE cl2.id_template = cl.templateId
                      );

Pour chaque modèle référencé dans la requête externe, la sous-requête trouve la date de mise à jour maximale. Ceci est ensuite utilisé pour filtrer les enregistrements dans la requête externe.


4 commentaires

Ce n'était pas moi, la seule chose que j'ai remarquée avec cette solution est qu'un modèle qui n'a jamais été modifié n'est pas inclus. Si la création n'est pas incluse dans la table ChangeLog.


@EdCallahan. . . Cela ne semble pas probable car la réponse acceptée suppose également que tous les modèles sont dans le journal des modifications.


J'ai juste remarqué que j'étais moi aussi en baisse. Quoi qu'il en soit, comment évaluez-vous l'utilisation d'une fonction de fenêtre? Ils sont tout simplement cool. ;)


@EdCallahan est là de toute façon pour exécuter cette fonction de fenêtre (avec row_number) ou similaire dans MySQL, je ne peux pas exécuter votre requête et je voudrais configurer une requête qui inclut également des modèles qui n'ont pas été modifiés pour une autre partie de mon projet



0
votes

Vous pouvez utiliser deux JOIN pour obtenir les informations de toutes les tables, puis utiliser un SUBQUERY pour obtenir la valeur maximale du champ updated_at, comme ceci:

SELECT 
    t.id as template_id, t.name as template_name, 
    u.name as user_name, 
    c.updated_at as changelog_updated_at 
FROM 
    changelogs c

INNER JOIN templates t on c.id_template = t.id
INNER JOIN users u on c.id_user = u.id

WHERE 
  c.updated_at = 
    (SELECT MAX(updated_at) FROM changelogs c2 where c2.id_template = t.id)

ORDER BY t.template_name 


0 commentaires

0
votes

Je pense qu'une fonction de fenêtre est votre ami ici. Je n'ai pas créé d'exemples de tables pour l'exécuter, alors il y a un type-o ou deux:

select *
from (

    select *
        ,row_number() over (partition by t.id order by c.last_edited_at desc) row
        from Templates t
        left join ChangeLog c
        on t.id=c.id_template
        left join Users u
        on c.id_user=u.id

) t
where row=1


0 commentaires