SQL Group By和Join

时间:2010-04-13 20:53:16

标签: sql linq-to-sql linq-to-nhibernate

我觉得完全愚蠢。我的sql生锈了。

我有两个表,Message和MessageThread。使用ParentTHreadID作为外键,每条消息属于一个MessageThread。你可能会看到它的发展方向。

好吧,我想做这样的事情。我想从表,消息和线程中获取列,但是消息的datecreated是该线程中的最大值。因此,每条记录都将包含一个消息记录的线程列和列,该消息记录是该消息线程中最新发布的消息记录。

这是我到目前为止获得的所有线程列和消息的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到sql或linq到nhibernate。

谢谢, 克雷格

3 个答案:

答案 0 :(得分: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 

这应该可以获得包含两个嵌套查询的所有列。

答案 1 :(得分: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)

这具有仅选择一行的效果,该行具有该线程的最大日期。 此外,这意味着您可以选择所需的列,而无需对其进行子查询,从而减少查询必须执行的表扫描或索引扫描的数量。

答案 2 :(得分: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的数据。在这种情况下,只需加入Message。