2010-04-13 5 views
1

Je me sens totalement stupide. Je suis rouillé avec mon sql.SQL Group Par et Rejoindre

J'ai deux tables, Message et MessageThread. Chaque message appartient à un MessageThread utilisant ParentTHreadID en tant que clé étrangère. Vous pouvez probablement voir où cela se passe.

Eh bien, je veux faire quelque chose comme ça. Je veux obtenir des colonnes des deux tables, des messages et des discussions, mais où le datecreated du message est le maximum dans ce fil. Chaque enregistrement contiendra donc les colonnes de threads et les colonnes d'un enregistrement de message le plus récent publié dans ce thread de message.

Voici ce que j'ai jusqu'ici qui me donne toutes les colonnes de fil et l'ID du message. Cela fonctionne, mais utilise une sous-requête et je devrais faire un tas d'autres sous-requêtes pour obtenir les autres colonnes. Yuck.

select t.*, (select top 1 m.ID from Message m where m.ParentThreadID = t.ID order by DateCreated desc) as MessageID
from MessageThread t

points de bonus à tous ceux qui peuvent non seulement me donner sql, mais LINQ to SQL ou LINQ to NHibernate.

Merci, Craig

Répondre

0

La solution: plus !! sous-requêtes

select * from (
    select t.*, (
     select top 1 ID 
     from Message 
     where ParentThreadID = t.ID 
     order by DateCreated desc 
    ) as MessageID 
    from MessageThread t 
) tm 
    left join Message m on tm.MessageID = m.ID 

Ceci devrait vous permettre d'obtenir toutes les colonnes avec deux requêtes imbriquées.

+0

Je suppose que c'est assez impossible dans linq? – fregas

+0

Probablement pas, mais je ne parle pas couramment linq. – Blorgbeard

0

Comment cela fonctionnerait pour vous:

SELECT (whateverYouWant) 
FROM Message m, MessageThread mt 
WHERE m.ParentThreadID = mt.ID 
AND mt.DateCreated = (SELECT MAX(mt2.DateCreated) 
         FROM MessageThread mt2 
         WHERE mt2.ID= mt.ID) 

Cela a pour effet de sélectionner une seule ligne, celui qui a la date maximale pour ce thread. En outre, cela signifie que vous pouvez sélectionner les colonnes de votre choix sans devoir les sous-interroger, ce qui réduit le nombre d'analyses de table ou d'index que votre requête doit effectuer.

0

D'abord, vous pouvez écrire cela sans une table dérivée (comme dans votre OP) en utilisant un sous-requête comme ceci:

Select ... 
From MessageThread As T 
Where Id = (
      Select TOP 1 M.Id 
      From Message As M 
      Where M.ParentThreadId = T.Id 
      Order By DateCreated Desc 
      ) 

Le LINQ équivalent serait quelque chose comme:

var query = from messageThread in MessageThread 
       join message in Message on message.ParentThreadId == messageThread.Id 
       let first = (messages.Where(m => m.ParentThreadId == messageThread.Id).OrderByDescendng(m => m.DateCreated).First().Id) 
       where messageThread.Id == first 
       select new {MessageThread = messageThread, Message = Message}; 

EDIT Vous avez mentionné que vous avez également besoin des données du message. Dans ce cas, rejoignez simplement Message.

+0

J'ai besoin à la fois du messagethread et du message, mais le message doit être le message le plus récent le plus récent dans ce thread. Donc, j'ai besoin comme select nouveau {messageThread, message} quelque part – fregas

+0

@fregas - Si tel est le cas, alors simplement se joindre à Message. – Thomas