2010-04-13 112 views
1

我感觉完全愚蠢。我生我的sql。SQL Group By and Join

我有两个表,Message和MessageThread。每条消息都属于一个使用ParentTHreadID作为外键的MessageThread。你可能会看到这是怎么回事。

嗯,我想要做这样的事情。我想从两个表,消息和线程中获取列,但创建的消息的date是该线程中的最大值。因此,每条记录都将包含该消息线程中最近发布的一条消息记录的线程列和列。

这是我到目前为止所得到的所有线程列和消息的ID。它的工作原理,但使用子查询,我不得不做一堆其他子查询来获得其他列。呸。

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

奖励积分的人谁不能只给我的SQL,但是的LINQ to SQL或LINQ到NHibernate的。

谢谢, 克雷格

回答

0

解决办法:更多的子查询!

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 

这应该让你有两个嵌套查询的所有列。

+0

我认为这在linq中是不可能的? – fregas 2010-04-13 21:43:09

+0

可能不是,但我真的不是流利的linq。 – Blorgbeard 2010-04-13 22:52:43

0

如何将这项工作对您:

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) 

这有只选择一列,这对于该线程的最大日一个的效果。 此外,它意味着你可以选择你想要的任何列而不必对它们进行子查询,从而减少查询必须执行的表扫描或索引扫描的次数。

0

首先,你可以(在你的OP)通过使用子查询,像这样写这篇文章没有派生表:

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 
      ) 

等效LINQ会是这样的:

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

编辑你提到你也需要消息中的数据。在这种情况下,只需加入Message。

+0

我需要messagethread和消息,但消息需要是该线程中最近的1条消息。 所以我需要像选择新的{messageThread,消息}某处 – fregas 2010-04-14 19:35:26

+0

@fregas - 如果是这样的话,那么只需加入到消息。 – Thomas 2010-04-14 19:44:36