SQL Group By и Join - PullRequest
       24

SQL Group By и Join

1 голос
/ 14 апреля 2010

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

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

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

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

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

Бонус указывает любому, кто может не только дать мне sql, но и linq к sql или linq к nhibernate.

Спасибо, Craig

Ответы [ 3 ]

0 голосов
/ 14 апреля 2010

Как это будет работать для вас:

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 голосов
/ 14 апреля 2010

Во-первых, вы можете написать это без производной таблицы (как в вашем 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};

РЕДАКТИРОВАТЬ Вы упомянули, что вам также нужны данные из сообщения. В этом случае просто присоединитесь к сообщению.

0 голосов
/ 14 апреля 2010

Решение: больше подзапросов !!

  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 

Это должно получить все столбцы с двумя вложенными запросами.

...