根据消息类型获取最后加载的消息

时间:2014-02-17 15:22:45

标签: sql tsql

我有一个包含不同消息的表,每个消息都有一个messageType字段。我需要为每个messageType填充上次加载的消息的ASP.NET列表控件。我的sql语句返回一切是:

SELECT MessageTypes.MessageType MessageType
    ,Messages.MessageDate
    ,Messages.ValueDate
    ,Messages.MessageReference
    ,Messages.Beneficiary
    ,Messages.StatusId
    ,MessageStatus.STATUS
    ,BICProfile.BIC
FROM Messages
INNER JOIN MessageStatus
    ON Messages.StatusId = MessageStatus.Id
INNER JOIN MessageTypes
    ON Messages.MessageTypeId = MessageTypes.MessageTypeId
INNER JOIN BICProfile
    ON Messages.SenderId = dbo.BICProfile.BicId
WHERE (BICProfile.BIC = 'someValue')
    AND Messages.StatusId IN (4, 5, 6)

所以我需要为每种消息类型提取最后一条消息。

修改 的 关于statusId的一些说明。这些基本上与用户角色一起使用,可以看到哪些消息。所以,我需要为给定的消息类型返回最后加载的消息。实际上,只希望为每种消息类型返回1条消息。 messageId是唯一的,消息日期可以是相同的。

3 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER()函数按邮件日期为每条邮件分配排名(对于每种邮件类型,再次从1开始),然后将结果限制为排名靠前的邮件:

WITH AllMessages AS
(   SELECT  MessageTypes.MessageType, 
            Messages.MessageDate, 
            Messages.ValueDate, 
            Messages.MessageReference, 
            Messages.Beneficiary, 
            Messages.StatusId,
            MessageStatus.Status, 
            BICProfile.BIC,
            RowNumber = ROW_NUMBER() OVER(PARTITION BY Messages.MessageTypeId 
                                            ORDER BY Messages.MessageDate DESC)
    FROM    Messages 
            INNER JOIN MessageStatus 
                ON Messages.StatusId = MessageStatus.Id 
            INNER JOIN MessageTypes 
                ON Messages.MessageTypeId = MessageTypes.MessageTypeId 
            INNER JOIN BICProfile  
                ON Messages.SenderId = dbo.BICProfile.BicId 
    WHERE   BICProfile.BIC = 'someValue'
    AND     Messages.StatusId IN (4, 5, 6)
)
SELECT  MessageType, 
        MessageDate, 
        ValueDate, 
        MessageReference, 
        Beneficiary, 
        StatusId,
        Status, 
        BIC 
FROM    AllMessages
WHERE   RowNumber = 1;

如果您无法使用ROW_NUMBER,则可以使用子查询获取每种类型的最新消息日期:

SELECT  Messages.MessageTypeID, MessageDate = MAX(Messages.MessageDate)
FROM    Messages
        INNER JOIN BICProfile  
            ON Messages.SenderId = dbo.BICProfile.BicId 
WHERE   BICProfile.BIC = 'someValue'
AND     Messages.StatusId IN (4, 5, 6)
GROUP BY Messages.MessageTypeID

然后将内容加入到您的主要查询中以过滤结果:

SELECT  MessageTypes.MessageType, 
        Messages.MessageDate, 
        Messages.ValueDate, 
        Messages.MessageReference, 
        Messages.Beneficiary, 
        Messages.StatusId,
        MessageStatus.Status, 
        BICProfile.BIC
FROM    Messages 
        INNER JOIN MessageStatus 
            ON Messages.StatusId = MessageStatus.Id 
        INNER JOIN MessageTypes 
            ON Messages.MessageTypeId = MessageTypes.MessageTypeId 
        INNER JOIN BICProfile  
            ON Messages.SenderId = dbo.BICProfile.BicId 
        INNER JOIN 
        (   SELECT  Messages.MessageTypeID, 
                    MessageDate = MAX(Messages.MessageDate)
            FROM    Messages
                    INNER JOIN BICProfile  
                        ON Messages.SenderId = dbo.BICProfile.BicId 
            WHERE   BICProfile.BIC = 'someValue'
            AND     Messages.StatusId IN (4, 5, 6)
            GROUP BY Messages.MessageTypeID
        ) AS MaxMessage
            ON MaxMessage.MessageTypeID = Messages.MessageTypeID
            AND MaxMessage.MessageDate = Messages.MessageDate
WHERE   BICProfile.BIC = 'someValue'
AND     Messages.StatusId IN (4, 5, 6);

N.B如果最新消息日期在多个消息中很常见,则第二种方法将为每种消息类型返回多行。通过将ROW_NUMBER替换为RANK

,可以在第一个查询中复制此行为

修改

如果您有多个具有相同日期的消息并且只想返回其中一个消息,则需要在row_number函数中扩展排序,即如果您想在有关系时选择具有最大ID的消息做到:

RowNumber = ROW_NUMBER() OVER(PARTITION BY Messages.MessageTypeId 
                                ORDER BY Messages.MessageDate DESC,
                                        Messages.MessageID DESC)

所以完整的查询将是:

WITH AllMessages AS
(   SELECT  MessageTypes.MessageType, 
            Messages.MessageDate, 
            Messages.ValueDate, 
            Messages.MessageReference, 
            Messages.Beneficiary, 
            Messages.StatusId,
            MessageStatus.Status, 
            BICProfile.BIC,
            RowNumber = ROW_NUMBER() OVER(PARTITION BY Messages.MessageTypeId 
                                            ORDER BY Messages.MessageDate DESC,
                                                    Messages.MessageID DESC)
    FROM    Messages 
            INNER JOIN MessageStatus 
                ON Messages.StatusId = MessageStatus.Id 
            INNER JOIN MessageTypes 
                ON Messages.MessageTypeId = MessageTypes.MessageTypeId 
            INNER JOIN BICProfile  
                ON Messages.SenderId = dbo.BICProfile.BicId 
    WHERE   BICProfile.BIC = 'someValue'
    AND     Messages.StatusId IN (4, 5, 6)
)
SELECT  MessageType, 
        MessageDate, 
        ValueDate, 
        MessageReference, 
        Beneficiary, 
        StatusId,
        Status, 
        BIC 
FROM    AllMessages
WHERE   RowNumber = 1;

答案 1 :(得分:2)

试试这个:

SELECT MT.MessageType
    ,X.MessageDate
    ,X.ValueDate
    ,X.MessageReference
    ,X.Beneficiary
    ,X.StatusId
    ,X.STATUS
    ,X.BIC
FROM MessageTypes MT
OUTER APPLY -- or CROSS APPLY
(
SELECT TOP 1
    M.MessageDate
    ,M.ValueDate
    ,M.MessageReference
    ,M.Beneficiary
    ,M.StatusId
    ,MS.STATUS
    ,B.BIC
FROM Messages M
INNER JOIN MessageStatus MS
    ON M.StatusId = MS.Id
INNER JOIN BICProfile B
    ON M.SenderId = B.BicId
WHERE (B.BIC = 'someValue')
    AND M.StatusId IN (4, 5, 6)
    AND M.MessageTypeId = MT.MessageTypeId
ORDER BY M.MessageDate DESC
) X

答案 2 :(得分:0)

您可以使用简单的子查询来获取每种消息类型的最新消息日期,并使用它来过滤最后一条消息。见下文:

如果您想要每个类别的最后一条消息,请仅显示该消息的状态为4,5或6 :(如果消息的状态为其他类别,则该类别无效)

SELECT MessageTypes.MessageType MessageType,
       Messages.MessageDate,
       Messages.ValueDate,
       Messages.MessageReference,
       Messages.Beneficiary,
       Messages.StatusId,
       MessageStatus.STATUS,
       BICProfile.BIC
  FROM Messages
 INNER JOIN MessageStatus
    ON Messages.StatusId = MessageStatus.Id
 INNER JOIN MessageTypes
    ON Messages.MessageTypeId = MessageTypes.MessageTypeId
 INNER JOIN BICProfile
    ON Messages.SenderId = dbo.BICProfile.BicId
 WHERE BICProfile.BIC = 'someValue'
   AND Messages.StatusId IN (4, 5, 6)
   and messages.messagedate =
       (select max(x.messagedate)
          from messages x
         where x.messagetypeid = messages.messagetypeid)

如果您想要每个类别的最后一条消息,只需要该消息的状态为4,5或6 :(如果消息的状态是其他类型,那么该类别没有结果)AND IN THE一个领带的事件你想要有最高的消息ID的消息

SELECT MessageTypes.MessageType MessageType,
       Messages.MessageDate,
       Messages.ValueDate,
       Messages.MessageReference,
       Messages.Beneficiary,
       Messages.StatusId,
       MessageStatus.STATUS,
       BICProfile.BIC
  FROM Messages
 INNER JOIN MessageStatus
    ON Messages.StatusId = MessageStatus.Id
 INNER JOIN MessageTypes
    ON Messages.MessageTypeId = MessageTypes.MessageTypeId
 INNER JOIN BICProfile
    ON Messages.SenderId = dbo.BICProfile.BicId
 WHERE BICProfile.BIC = 'someValue'
   AND Messages.StatusId IN (4, 5, 6)
   and messages.messagedate =
       (select max(x.messagedate)
          from messages x
         where x.messagetypeid = messages.messagetypeid)
   and messages.messageid =
       (select max(x.messageid)
          from messages x
         where x.messagetypeid = messages.messagetypeid
           and x.messagedate = messages.messagedate)

^^ CHANGE“messageid”到表格上的任何字段MESSAGES表示ID。

如果您希望每个类别的最后一条消息以及每个状态为4,5和6(如果该类别中存在任何/全部)

SELECT MessageTypes.MessageType MessageType,
       Messages.MessageDate,
       Messages.ValueDate,
       Messages.MessageReference,
       Messages.Beneficiary,
       Messages.StatusId,
       MessageStatus.STATUS,
       BICProfile.BIC
  FROM Messages
 INNER JOIN MessageStatus
    ON Messages.StatusId = MessageStatus.Id
 INNER JOIN MessageTypes
    ON Messages.MessageTypeId = MessageTypes.MessageTypeId
 INNER JOIN BICProfile
    ON Messages.SenderId = dbo.BICProfile.BicId
 WHERE BICProfile.BIC = 'someValue'
   AND Messages.StatusId IN (4, 5, 6)
   and messages.messagedate =
       (select max(x.messagedate)
          from messages x
         where x.messagetypeid = messages.messagetypeid
           and x.statusid = messages.statusid)

如果您想要状态为4,5或6的每个类别的最后一条消息:(未考虑其他状态的消息)

SELECT MessageTypes.MessageType MessageType,
       Messages.MessageDate,
       Messages.ValueDate,
       Messages.MessageReference,
       Messages.Beneficiary,
       Messages.StatusId,
       MessageStatus.STATUS,
       BICProfile.BIC
  FROM Messages
 INNER JOIN MessageStatus
    ON Messages.StatusId = MessageStatus.Id
 INNER JOIN MessageTypes
    ON Messages.MessageTypeId = MessageTypes.MessageTypeId
 INNER JOIN BICProfile
    ON Messages.SenderId = dbo.BICProfile.BicId
 WHERE BICProfile.BIC = 'someValue'
   AND Messages.StatusId IN (4, 5, 6)
   and messages.messagedate =
       (select max(x.messagedate)
          from messages x
         where x.messagetypeid = messages.messagetypeid
           and x.statusid in (4, 5, 6))