按语法分区

时间:2019-03-28 13:57:05

标签: sql-server sql-server-2016 partitioning

我有以下语句,该语句用于获取特定DDI的最新数据行。我现在想做的是用一长串的替换列表替换where语句中的单个DDI,但每个DDI仍然只有最新的一行。我非常确定我需要使用OVER和PARTITION BY来为每个DDI获取一个单独的窗口,但是即使阅读了Microsoft文档和更简化的教程,我仍然无法获得正确的语法。我怀疑我只需要朝正确的方向轻推即可。有人可以帮忙吗?

https://docs.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql?view=sql-server-2017

http://www.sqltutorial.org/sql-window-functions/sql-partition-by/

SELECT TOP 1
       [Start Time]
      ,[Agent Name]
      ,[Reference]
      ,[charged op. (sec)]
      ,[Type]         
      ,[Activation ID] as [actid]          
  FROM [iPR].[dbo].[InboundCallsView]    
  Where [type] = 'Normal operator call'    
  AND [DDI] = @DDI    
  Order By [Start Time] Desc

2 个答案:

答案 0 :(得分:2)

不知道如何计划处理DDI的多个值,但这可能是一个问题。最好的方法是使用表值参数。如果传入定界列表,则也必须拆分字符串,这不是处理此类问题的好方法。

此查询将为每个DDI返回最新的查询。

SELECT 
    [Start Time]
    , [Agent Name]
    , [Reference]
    , [charged op. (sec)]
    , [Type]
    , [actid]
from
(
    SELECT 
        [Start Time]
        , [Agent Name]
        , [Reference]
        , [charged op. (sec)]
        , [Type]
        , [actid]
        , RowNum = ROW_NUMBER() over(partition by DDI order by [Start Time] desc)
      FROM [iPR].[dbo].[InboundCallsView]

      where [type] = 'Normal operator call'
        --and [DDI] = @DDI
) x
where x.RowNum = 1

答案 1 :(得分:1)

因此,让我们假设一个包含此数据的表(注意我如何清除列名以删除空格,特殊字符等):

x == (int)(double)x;

正如您所说,您可以使用窗口函数来获取所需的内容。但是,让我向您展示不需要首先使用窗口函数的方法。

您要记录+---+------------------+--------+------+----+------+---+ | 1 | 2019-03-28 08:00 | agent1 | foo1 | 60 | foo1 | 1 | +---+------------------+--------+------+----+------+---+ | 1 | 2019-03-28 09:00 | agent2 | foo2 | 70 | foo2 | 2 | | 2 | 2019-03-27 08:00 | agent3 | foo3 | 80 | foo3 | 3 | | 2 | 2019-03-27 09:00 | agent4 | foo4 | 90 | foo4 | 4 | +---+------------------+--------+------+----+------+---+ 是该DDI的最大值的位置。您可以使用以下查询获取每个DDI的最大值StartTime

StartTime

然后,您可以将该查询加入基本表/视图中,以获取所需的记录。使用中间CTE,您可以执行以下操作:

SELECT
    ddi, 
    max_start = MAX(StartTime)
FROM InboundCallsView
GROUP BY ddi

现在,如果您真的想使用WINDOW函数,则可以使用WITH ddiWithMaxStart AS ( SELECT ddi, max_start = MAX(StartTime) FROM InboundCallsView GROUP BY ddi ) SELECT InboundCallsView.* FROM InboundCallsView INNER JOIN ddiWithMaxStart ON ddiWithMaxStart.ddi = InboundCallsView.ddi AND ddiWithMaxStart.max_start = InboundCallsView.StartTime 获得类似的效果:

ROW_NUMBER

请注意,使用此方法,您无需将基本视图/表连接到中间CTE。

您可以测试每种方法的性能,以查看哪种方法最适合您。