L'auteur d'un thread peut être NULL (son compte a été supprimé).
L'auteur d'un message peut être NULL (son compte a été supprimé).
Je souhaiterais, en une requête SQL unique :
1 - Récupérer l'ensemble des threads d'un forum donné
2 - Ordonnés par date du dernier message posté dans celui-ci
3 - Avec le nombre de messages de chacun de ses threads
4 - Avec l'auteur (pseudo) de celui qui a crée le thread
5 - Avec l'auteur (pseudo) du dernier message
Cette requête sera par la suite utilisée avec Doctrine (ORM PHP).
Pour 1, 2, 3 et 4 c'est ok, je bloque sur la 5.
SELECT t.*, u.pseudo AS author_pseudo, COUNT(m.id) AS total_messages, MAX(m.published_at) AS last_message_at
FROM thread t
LEFT JOIN user u ON t.author_id = u.id
INNER JOIN message m ON t.id = m.thread_id
WHERE forum_id = 4
GROUP BY t.id
ORDER BY last_message_at DESC
- Ajouter directement m.author_id AS last_message_by dans le SELECT, évidemment erreur :
SELECT list is not in GROUP BY clause and contains nonaggregated column 'sym_forum.m.author_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
- Ajouter une jointure entre messages & users puis ajouter le champ dans le select, même erreur
Un collègue m'a produit le code suivant (beaucoup trop complexe à mon niveau, je n'ai pas vu les notions utilisées) :
SELECT t.*, u.pseudo AS author_pseudo, m_last.published_at AS last_message_at, u_last.pseudo AS last_author
FROM thread t
LEFT JOIN user u ON t.author_id = u.id
JOIN message m_last on t.id = m_last.thread_id
LEFT JOIN user u_last on u_last.id = m_last.author_id
WHERE forum_id = :forum
AND CONCAT(m_last.published_at, m_last.id ) = (SELECT MAX(CONCAT(tmp.published_at, tmp.id )) FROM message tmp where t.id = tmp.thread_id)
ORDER BY last_message_at DESC
Cette-fois ci j'obtiens bien le pseudo de l'utilisateur qui a posté le dernier message mais plus le nombre total de messages dans le thread en question.
Vous l'aurez compris, dans ma solution "basique" il me manque un pseudo, dans sa solution "complexe" il manque le nombre total de messages.
Je ne sais plus comment raisonner, je reste bloqué.
Je pense que le "plus simple" est de décomposé ton besoin en sous-requêtes voire en vues...
L'idée c'est de créer, dans un premier temps, une vue qui te retourne les données du dernier message par thread :
CREATE VIEW vue_dernier_message AS
SELECT M.*, LM.nb_messages
FROM
(
-- Date dernier message par thread
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
) LM
INNER JOIN message M
ON LM.thread_id = M.id
AND LM.max_date = M.published_at;
Cette vue calcule dans une sous-requête la date du dernier message par thread et le nombre de messages par thread, puis récupère le contenu du dernier message.
Tu peux maintenant utiliser ta vue comme bon te semble pour faire ta requête globale :
SELECT
t.*,
u.pseudo AS author_pseudo,
DM.published_at AS last_message_at,
u_last.pseudo AS last_author,
DM.nb_messages
FROM
thread t
INNER JOIN vue_dernier_message DM
ON t.id = DM.thread_id
LEFT JOIN user u
ON t.author_id = u.id
LEFT JOIN user u_last
on u_last.id = dm.author_id
WHERE forum_id = :forum
ORDER BY last_message_at DESC;
Seul problème, mais qui vaut pour toute solution ... deux messages postés en simultané pour le même thread ...
Alors il faut décomposer la requête pour comprendre ce qui ne va pas ...
Si tu exécutes seulement ceci :
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
Obtiens-tu des valeurs, et dans ces valeurs vois-tu les thread_id souhaités ?
Si oui, si tu exécutes la vue complète :
SELECT M.*, LM.nb_messages
FROM
(
-- Date dernier message par thread
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
) LM
INNER JOIN message M
ON LM.thread_id = M.id
AND LM.max_date = M.published_at;
Obtiens-tu des valeurs, et dans ces valeurs vois-tu les thread_id souhaités ?
Si oui ... c'est étrange ... que retourne cette requête de contrôle :
SELECT t.*
FROM
thread t
LEFT JOIN vue_dernier_message DM
ON t.id = DM.thread_id
WHERE DM.thread_id IS NULL
Cette requête te retourne la liste des threads qui n'ont pas de lien dans la vue. Obtiens-tu des valeurs ?
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
J'obtiens en effet le résultat pour chacun des threads.
Si j'exécute la vue complète :
SELECT M.*, LM.nb_messages
FROM
(
-- Date dernier message par thread
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
) LM
INNER JOIN message M
ON LM.thread_id = M.id
AND LM.max_date = M.published_at;
Je n'obtiens aucun résultat.
Pour ce qui est de la requête de contrôle :
Autrement dit, le même résultat qu'un simple SELECT * FROM thread.
J'ai fait une erreur ... dans la vue la jointure doit se faire sur thread_id et pas sur id ...
SELECT M.*, LM.nb_messages
FROM
(
-- Date dernier message par thread
SELECT thread_id, MAX( published_at ) AS max_date, COUNT(*) AS nb_messages
FROM message
GROUP BY thread_id
) LM
INNER JOIN message M
ON LM.thread_id = M.thread_id -- correction ici
AND LM.max_date = M.published_at;
ce qui n'a plus rien à voir avec la structure que je souhaitais recevoir
-Steven a écrit:
Je souhaiterais, en une requête SQL unique :
1 - Récupérer l'ensemble des threads d'un forum donné
2 - Ordonnés par date du dernier message posté dans celui-ci
3 - Avec le nombre de messages de chacun de ses threads
4 - Avec l'auteur (pseudo) de celui qui a crée le thread
5 - Avec l'auteur (pseudo) du dernier message
Maintenant que la vue est corrigée, tu peux rédiger ta requête principale comme bon te semble ... Si le résultat attendu est celui donné dans ton dernier message, alors :
SELECT
t.id,
t.author_id,
t.forum_id,
t.created_at,
u.pseudo AS author_pseudo,
dm.published_at AS last_message_at,
u_last.pseudo AS last_author,
dm.nb_messages
FROM
thread t
INNER JOIN vue_dernier_message dm
ON t.id = dm.thread_id
INNER JOIN user u
ON t.author_id = u.id
INNER JOIN user ul
on ul.id = dm.author_id
WHERE t.forum_id = :forum
ORDER BY dm.last_message_at DESC;
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Discord d'entraide symfony
Soldat du code et enfant de la technologie.
Discord d'entraide symfony
Soldat du code et enfant de la technologie.
Discord d'entraide symfony
Soldat du code et enfant de la technologie.
Discord d'entraide symfony
Soldat du code et enfant de la technologie.
Discord d'entraide symfony
Soldat du code et enfant de la technologie.