t-sql选择基于首选项

时间:2017-07-14 01:57:54

标签: sql-server tsql

我的名为Table1的表格位于以下列:

  1. 的MessageId
  2. 消息
  3. 国家
  4. DateTimeStamp
  5. 州可以具有以下值:routingdeliveredrejected

    首次路由邮件时会插入记录。 然后在传递或拒绝邮件时插入记录。

    我想选择的是,

    1. 如果邮件包含两个状态为deliveredrouting的记录,则选择状态为delivered的记录。
    2. 如果邮件包含两个状态为rejectedrouting的记录,则选择状态为rejected的记录。
    3. 如果邮件只有一条状态为routing的记录,则按原样选择。
    4. 这是一种基于偏好的选择。任何帮助将不胜感激。

      IF OBJECT_ID('tempdb..#Table1', 'U') IS NOT NULL
      DROP TABLE #Table1;
      
      CREATE TABLE #Table1 (
      MessageId INT NOT NULL,
      [Message] VARCHAR(100) NOT NULL,
      [State] VARCHAR(10) NOT NULL,
      DateTimeStamp DATETIME --DEFAULT(GETDATE())
      );
      
      INSERT #Table1 (MessageId, Message, State, DateTimeStamp) VALUES 
      (1, 'xxx', 'routing', getdate()), 
      (2, 'xxx', 'delivered', dateadd(hh,1,getdate())),
      (3, 'yyy', 'routing', dateadd(hh,2,getdate())), 
      (4, 'yyy', 'rejected', dateadd(hh,3,getdate())),
      (5, 'aaa', 'routing', dateadd(hh,4,getdate())), 
      (6, 'zzz', 'routing', dateadd(hh,5,getdate())), 
      (7, 'zzz', 'unknown', dateadd(hh,6,getdate()))
      
      --=========================================================
      MessageId   Message State        DateTimeStamp
          1         xxx   routing     2017-07-14 09:07:16.840
          2         xxx   delivered   2017-07-14 10:07:16.840
          3         yyy   routing     2017-07-14 11:07:16.840
          4         yyy   rejected    2017-07-14 12:07:16.840
          5         aaa   routing     2017-07-14 13:07:16.840
          6         zzz   routing     2017-07-14 14:07:16.840
          7         zzz   unknown     2017-07-14 15:07:16.840
      
      --QUERY
      
      SELECT TOP 1 WITH TIES 
      t1.MessageId,
      t1.[Message],
      t1.[State],
      t1.DateTimeStamp FROM 
      #Table1 t1 ORDER BY ROW_NUMBER() OVER (PARTITION BY t1.Message ORDER BY IIF(t1.[State] = 'routing', 1, 0))
      
      --RESULTSET
      
      MessageId   Message    State    DateTimeStamp
      5            aaa    routing     2017-07-14 13:04:58.997
      2            xxx    delivered   2017-07-14 10:04:58.997
      4            yyy    rejected    2017-07-14 12:04:58.997
      7            zzz    unknown     2017-07-14 15:04:58.997
      
      --EXPECTED RESULTSET WITH DATETIMESTAMP DESC
      
      MessageId   Message    State    DateTimeStamp
      7            zzz    unknown     2017-07-14 15:04:58.997
      5            aaa    routing     2017-07-14 13:04:58.997
      4            yyy    rejected    2017-07-14 12:04:58.997
      2            xxx    delivered   2017-07-14 10:04:58.997
      

      如果我将结果集放在临时表中并从中进行选择并按datetimestamp desc排序,那么我只能实现预期的结果集。如果有一种方法可以不经过另一层插入并选择

      ,那将会很好

2 个答案:

答案 0 :(得分:2)

这看起来像是使用" TOP N WITH TIES" ...

的完美情况

检查以下内容:

IF OBJECT_ID('tempdb..#Table1', 'U') IS NOT NULL
DROP TABLE #Table1;

CREATE TABLE #Table1 (
    MessageId INT NOT NULL,
    [Message] VARCHAR(100) NOT NULL,
    [State] VARCHAR(10) NOT NULL,
    DateTimeStamp DATETIME DEFAULT(GETDATE())
    );

INSERT #Table1 (MessageId, Message, State) VALUES 
    (1, 'xxx', 'routing'), (1, 'yyy', 'delivered'),
    (2, 'xxx', 'routing'), (2, 'yyy', 'rejected'),
    (3, 'xxx', 'routing'), 
    (4, 'xxx', 'routing'), (4, 'yyy', 'delivered')

--=========================================================

SELECT TOP 1 WITH TIES 
    t1.MessageId,
    t1.[Message],
    t1.[State],
    t1.DateTimeStamp
FROM 
    #Table1 t1
ORDER BY
    ROW_NUMBER() OVER (PARTITION BY t1.MessageId ORDER BY IIF(t1.[State] = 'routing', 1, 0), t1.DateTimeStamp DESC);

修改后的OP编辑: 看看updat,看起来输出是正确的......你只想改变最终的排序。我就是这样,我建议在显示层中对其进行排序。也就是说,如果必须由SQL Server完成排序,您可以简单地将第一个查询用作派生表,并在外部查询中进行排序。见下文......

SELECT 
    m.MessageId,
    m.Message,
    m.State,
    m.DateTimeStamp
FROM 
    (
        SELECT TOP 1 WITH TIES 
            t1.MessageId,
            t1.[Message],
            t1.[State],
            t1.DateTimeStamp 
        FROM 
            #Table1 t1 
        ORDER BY 
            ROW_NUMBER() OVER (PARTITION BY t1.Message ORDER BY IIF(t1.[State] = 'routing', 1, 0), t1.DateTimeStamp DESC)
        ) m
ORDER BY 
    m.DateTimeStamp DESC;

HTH, 杰森

答案 1 :(得分:0)

以下查询应该适合您。您需要group by子句:

select * from 
(select [Message],COUNT([message]) AS MessageCount
from Table1
group by [Message]) AS T
where MessageCount = 1
相关问题