2010-03-30 6 views
4

Je ne me considère pas comme un novice à MySQL, mais celui-ci m'a déconcerté:Trompeur MySQL Query

J'ai un babillard et je veux tirer une liste de tous les plus récents messages regroupés par le fil ID.

Voici le tableau:

MB_Posts 
-ID 
-Thread_ID 
-Created_On (timestamp) 
-Creator_User (user_id) 
-Subject 
-Contents 
-Edited (timestamp) 
-Reported 

J'ai essayé beaucoup de choses différentes pour le garder simple mais je voudrais l'aide de la communauté sur celui-ci.

Juste pour botter ce là-bas ... celui-ci ne fonctionne pas comme prévu:

SELECT * FROM MB_Posts GROUP BY Thread_ID ORDER BY ID DESC 

résultats souhaités:

Un ensemble de messages les plus récents, un par TID

+1

Qu'espérez-vous que se passe-t-il et que se passe-t-il réellement? –

+1

Pourriez-vous préciser avec quels résultats vous vous attendez? Je ne suis pas sûr de ce que vous entendez par "groupé" dans ce contexte - que voulez-vous de retour? –

+0

Quels messages d'erreur ou résultats obtenez-vous lorsque vous exécutez cela? Ou ne fait-il rien du tout (0 lignes retournées)? Je suppose que le Thread_ID est le thread (conversation) dont le message fait partie? – jefflunt

Répondre

3

SELECT * 
FROM MB_Posts 
WHERE ID IN (SELECT MAX(ID) FROM MB_Posts GROUP BY Thread_ID) 

devrait vous donner ce dont vous avez besoin.

Pour plus de détails En savoir plus sur hidden columns in group by (dans votre requête d'origine toutes vos colonnes sauf ID_thread sont masquées)

+0

Hot putain! Ça a marché! Merci non. – jerebear

0

Lorsque vous utilisez GROUP BY, vous devez avoir une fonction d'agrégation dans la partie SELECT de l'instruction.

+0

J'ai pu utiliser GROUP BY et retourner les résultats dont j'ai besoin, mais s'il vous plaît expliquez comment j'implémenterais une fonction d'agrégat dans la partie SELECT et retournerais le résultat désiré ensemble. – jerebear

0

Ok, j'ai une suggestion. Faites-moi savoir:

SELECT 
    MB_Posts.*, 
    (SELECT 
     GROUP_CONCAT(CreatedOn ORDER BY CreatedOn DESC) 
     FROM MB_Posts AS P 
     WHERE P.Thread_ID = MB_Posts.Thread_ID) 
    AS `sort` 
FROM MB_Posts 
ORDER BY `sort` DESC, CreatedOn DESC 
+0

C'est si je voulais sélectionner le message le plus récent à partir d'un seul fil. C'est couvert. Ce que je veux, c'est le post le plus récent pour CHAQUE thread à la suite d'une seule requête. – jerebear

+0

Pas de soucis. Merci pour les commentaires. – jerebear

+0

J'ai édité ma réponse avec quelque chose de mieux, je pense. – Jage

0

Voici une autre façon:

SELECT * FROM mb_posts ORDER BY ID DESC 

threadsHistory = array(); 
while (row) 
{ 
    if (row) NOT IN threadsHistory 
    { 
     add values to array (for example thread_ID and postID) 
     count++; 
    } 
    if count == 10 break; 
} 

ce n'est pas exactement une façon agréable et propre, mais il devrait fonctionner avec un peu de torsion

+0

Je l'ai essayé. J'ai essayé beaucoup de choses ... avoir du mal avec la syntaxe actuelle. J'ai essayé JOINS, Nexted Queries et toutes sortes d'agrégateurs. C'est juste un problème délicat. – jerebear

+0

En effet, j'essayais simplement une de mes bases de données pour trouver une solution mais pas de succès. Vous pouvez toujours utiliser une simple boucle de code si cela ne vous dérange pas. – mspir

+0

J'ai édité la réponse, c'est un moyen qui fonctionne à coup sûr, mais ce n'est pas la façon la plus agréable et la plus propre d'y aller, je suppose. – mspir

0

GROUP BY prévoit revenir une rangée par groupe unique par exemple

SELECT COUNT(*) FROM mb_post GROUP BY thread_id; 

Renvoie le nombre de messages dans chaque tâche.

Vous aurez besoin de faire un ordre par thread_id, id, puis gérer par programme le "groupement" par ce que vous voulez, par exemple.

for (row in rows) { 
    print("<tr><th>"); 
    if (row["thread_id"] != prev_id) { 
     print(thread_id) 
     prev_id = thread_id; 
    } 
    print("</th>") 
+0

Je comprends. Mais GROUP BY renverra l'instance FIRST d'un élément en fonction du groupe et ignorera une instruction ORDER BY à la fin. Cette approche semblait la plus simple mais cela ne marchera pas. – jerebear

+0

Oui, c'est pourquoi vous devrez modifier la requête SELECT. SELECT * FROM mb_post ORDER BY Created_On DESC sélectionnera tous les articles triés par date de création dans un ordre décroissant, puis vous pourrez appliquer le code ci-dessus. – mspir

+0

Merde ... non cela ne fonctionnera pas ... vous devrez également changer la vérification pour les discussions déjà affichées. Peut-être en ajoutant une valeur à un tableau chaque fois que vous en rencontrez un nouveau, et quand le tableau atteint la taille de X, vous pouvez arrêter la boucle. – mspir

0

Donnez un tourbillon et voyez si cela correspond à ce que vous voulez. Cela devrait vous montrer les 100 derniers messages et les résultats reviendront triés par le fil auquel ils appartiennent.

SELECT MB_Posts.* 
    FROM MB_Posts 
    INNER JOIN (
    SELECT ID FROM MB_Posts ORDER BY Created_On DESC LIMIT 0, 100 
) as MostRecentPosts ON MB_Posts.ID = MostRecentPosts.ID 
    ORDER BY Thread_ID, Created_On DESC; 

Sur la base de votre révision « Un ensemble de messages les plus récents, un par thread ID », la table créée à partir de la sous-requête peut être créée en utilisant un peu concat et comparer la magie. Cela dépendra de ce que sont vos types de colonne, mais devrait fonctionner pour la plupart. L'idée de ces deux solutions consiste à utiliser une sous-requête pour gérer votre processus d'agrégation et à déterminer les ID des enregistrements souhaités, puis à joindre la table aux résultats de cette sous-requête pour récupérer le reste des données de la ligne . GROUP BY remplace BY ORDER BY (sans exceptions)

SELECT MB_Posts.* 
    FROM MB_Posts 
    INNER JOIN (
    SELECT TRIM(LEADING '0' FROM 
     SUBSTRING(MAX(CONCAT(UNIX_TIMESTAMP(Created_On), LPAD(ID,15,'0'))), -15)) AS ID 
    FROM MB_Posts 
    GROUP BY Thread_ID 
) as MostRecentPostPerThread ON MB_Posts.ID = MostRecentPostPerThread.ID 
    ORDER BY Thread_ID, Created_On DESC; 
+0

Essayé. Il retourne tous les messages dans la table. :( – jerebear

+0

Quelle version de mysql utilisez-vous peut-être? Je viens de retester ce local pour vérifier qu'il renvoie correctement les 100 entrées les plus récentes. –

+0

Selon vos exigences révisées, aviez-vous supprimé la limite 0,100 dans la première réponse? Cela vous aurait certainement rendu chaque poste. J'ai ajouté une solution basée sur vos besoins révisés qui permet de grouper par un champ, de trier par un autre, et de saisir l'identifiant associé en insérant l'ID dans le champ de tri puis de l'enlever après le tri du groupe (max) opération. –

0

Hum ... Est-ce que created_on ou modifié déterminer « le plus récent? »

Présumant created_on est ce qui voulait:

SELECT ID_thread, MAX (created_on) DE GROUPE MB_Posts PAR ID_thread;

donne l'horodatage le plus récent par Thread_ID. Ceux-ci à MB_Posts semi-jointure avec quelque chose comme

SELECT * FROM MB_Posts JOIN (SELECT ID_thread, MAX (created_on) AS created_on DE GROUPE MB_Posts PAR ID_thread) DERNIERES UTILISATION (ID_thread, created_on);

+0

Celui-ci a également travaillé! Merci JayDee – jerebear