2010-04-13 5 views
1

Я чувствую себя абсолютно глупо. Я ржавый с моим sql.SQL Group By and Join

У меня есть две таблицы, Message и MessageThread. Каждое сообщение принадлежит одному MessageThread с использованием ParentTHreadID в качестве внешнего ключа. Вероятно, вы можете увидеть, где это происходит.

Ну, я хочу сделать что-то подобное. Я хочу получить столбцы из обеих таблиц, сообщений и потоков, но там, где дата datecreated является максимальным в этом потоке. Таким образом, каждая запись будет содержать столбцы потоков и столбцы для одной записи сообщения, которая является самой последней опубликованной в этом потоке сообщений.

Вот что у меня есть до сих пор, что дает мне все столбцы потоков и идентификатор сообщения. Он работает, но использует подзапрос, и мне придется собрать кучу других подзапросов, чтобы получить другие столбцы. Тьфу.

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.

Спасибо, Craig

ответ

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

+0

Наверное, нет, но я действительно не так свободно владею linq. – Blorgbeard

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

EDIT Вы упомянули, что вам нужны данные из сообщения. В этом случае просто присоединитесь к сообщению.

+0

Мне нужно как messagethread, так и сообщение, но сообщение должно быть первым самым последним сообщением в этом потоке. Так что мне нужно, как выбрать новый {messageThread, message} где-то – fregas

+0

@fregas - Если это так, то просто присоединитесь к сообщению. – Thomas