SQL — возвращает только самую последнюю строку

#sql-server

#sql-сервер

Вопрос:

Я работаю над отчетом о устаревании для учетных записей за 30 дней и присоединяюсь к таблице «Комментарий», потому что AP хочет увидеть самый последний комментарий, если он существует для клиента.

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

Когда я присоединяюсь к таблицам, все работает, но он возвращает первый комментарий, а не последний.

Как я могу заставить его искать несколько строк для одного и того же клиента, а затем возвращать самый последний комментарий?

* Примечание — В таблице комментариев нет дат, просто поле начинается с 1000 и увеличивается для каждой новой строки комментария

Это то, что у меня есть прямо сейчас:

 SELECT        
    dbo.[Pioneer-CO$Purchase Header].No_, 
    dbo.[Pioneer-CO$Purchase Line].[Amt_ Rcd_ Not Invoiced], 
    dbo.[Pioneer-CO$Purch_ Rcpt_ Header].[Posting Date], 
    dbo.[Pioneer-CO$Comment Line].[Comment], 
    dbo.[Pioneer-CO$Purchase Header].[Sell-to Customer No_]
FROM
    dbo.[Pioneer-CO$Purchase Header] 
INNER JOIN
    dbo.[Pioneer-CO$Purchase Line] ON dbo.[Pioneer-CO$Purchase Header].No_ = dbo.[Pioneer-CO$Purchase Line].[Document No_] 
INNER JOIN
    dbo.[Pioneer-CO$Purch_ Rcpt_ Header] ON dbo.[Pioneer-CO$Purchase Header].No_ = dbo.[Pioneer-CO$Purch_ Rcpt_ Header].[Order No_] 
INNER JOIN
    dbo.[Pioneer-CO$Comment Line] ON dbo.[Pioneer-CO$Purchase Header].[Sell-to Customer No_] = dbo.[Pioneer-CO$Comment Line].[No_]
WHERE
    (dbo.[Pioneer-CO$Purch_ Rcpt_ Header].[Posting Date] < DATEADD(day, - 30, GETDATE()))
GROUP BY 
    dbo.[Pioneer-CO$Purchase Header].No_, 
    dbo.[Pioneer-CO$Purchase Line].[Amt_ Rcd_ Not Invoiced], 
    dbo.[Pioneer-CO$Purch_ Rcpt_ Header].[Posting Date], 
    dbo.[Pioneer-CO$Comment Line].[Comment], 
    dbo.[Pioneer-CO$Purchase Header].[Sell-to Customer No_]
HAVING        
    (dbo.[Pioneer-CO$Purchase Line].[Amt_ Rcd_ Not Invoiced] > '0')
ORDER BY 
    dbo.[Pioneer-CO$Purch_ Rcpt_ Header].[Posting Date] DESC
  

Комментарии:

1. Помимо описанной вами проблемы, имейте в виду, что, поскольку вы используете только ВНУТРЕННИЕ объединения, если у клиента вообще нет комментариев, они не будут отображаться в отчете, независимо от того, сколько лет их задолженности.

2. [posting date] desc вернет первую / последнюю строку, поскольку по убыванию означает «самая новая первая». попробуйте asc вместо этого — сначала самый старый

Ответ №1:

Я бы использовал что-то вроде этого

 select customer.*, lastComment.*
from account
cross apply (select top 1 * from comment where
    comment.customerId=customer.customerId order by commentnumber desc) lastComment
where customer.age>30
  

Если вам нужно включить клиентов без комментариев, используйте outer apply вместо cross apply

Ответ №2:

Я бы использовал следующий запрос:

 OUTER APPLY
(select top 1 [Comment] from dbo.[Pioneer-CO$Comment Line] where dbo.[Pioneer-CO$Purchase Header].[Sell-to Customer No_] = dbo.[Pioneer-CO$Comment Line].[No_] order by [Posting Date] desc) Comments
  

Кроме того, используйте Comments.[Comment] в инструкции SELECT вместо dbo.[Pioneer-CO$Comment Line].[Comment]

dbo.Таблица [Pioneer-CO$Comment Line] должна быть ВНЕШНЕЙ, ПРИМЕНЯЮЩЕЙ соединение в запросе. Кроме того, упорядочивайте комментарии по дате публикации или добавочному идентификатору.

Ответ №3:

Вы должны посмотреть на идентификатор или первичный ключ, я бы предположил, что более новые комментарии имеют более высокий идентификатор. Вы могли бы объединить таблицы и выполнить Max (ID) или искать последнюю временную метку, если вы используете ее в своей таблице.

Комментарии:

1. Я довольно новичок в SQL, и у меня возникли проблемы с использованием функции MAX. Есть предложения о том, как будет выглядеть этот код?

2. Поиск @Rkindred MAX — MSDN . MSDN от Microsoft — отличный ресурс по синтаксису и официальному использованию ключевых слов SQL. Кроме того, поймите, что если функция не выполняется сама по себе, у вас ДОЛЖЕН быть столбец (неагрегированный), который появляется в SELECT , также появляется в GROUP BY предложении. Обзор со ссылками на другие агрегаты см. в разделе АГРЕГАТНЫЕ ФУНКЦИИ — MSDN

Ответ №4:

Похоже, у вас отношение клиентов к комментариям равно 1 ко многим (0). Как насчет того, чтобы попробовать что-то вроде этого,

 SELECT TOP 1 Customers.*, Comments.*
FROM Customers
JOIN Customers ON Customers.Id = Comments.Id
ORDER BY Comments.Id DESC
  

Следующее добавлено после комментариев Bib

Вы также можете попробовать следующее

 SELECT Customers.*, Comments.*
FROM Comments
JOIN
(SELECT MAX(Id) As CId FROM Comments GROUP BY CustomerId) AS CommentsMAX
ON CommentsMAX.CId = Comments.ID
JOIN 
Customers ON Customers.Id = Comments.Id
  

Комментарии:

1. Это вернет только одну строку, это будет последний комментарий и клиент, с которым связан этот комментарий