Разделение по синтаксису - PullRequest
0 голосов
/ 28 марта 2019

У меня есть следующий оператор, который работает, чтобы получить самую последнюю строку данных для определенного DDI. Теперь я хочу заменить одиночный DDI в операторе where длинным списком, но для каждого из них по-прежнему есть только самая последняя строка. Я уверен, что мне нужно использовать 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 ]

2 голосов
/ 28 марта 2019

Не уверен, как вы планируете обрабатывать несколько значений для 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 голос
/ 28 марта 2019

Итак, давайте предположим таблицу с этими данными (обратите внимание, как я очистил имена столбцов для удаления пробелов, специальных символов и т. Д.):

+---+------------------+--------+------+----+------+---+
| 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 |
+---+------------------+--------+------+----+------+---+

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

Вы хотите записи, где StartTime является максимальным значением для этого DDI.Вы можете получить максимум StartTime для каждого DDI с помощью следующего запроса:

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

Затем вы можете присоединить этот запрос к вашей базовой таблице / представлению, чтобы получить нужные записи.Используя промежуточный CTE, вы можете сделать следующее:

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

Теперь, если вы действительно хотите использовать функции WINDOW, вы можете использовать ROW_NUMBER для аналогичного эффекта:

WITH 
    ddiWithRowNumber AS
    (
        SELECT
            InboundCallsView.*, 
            rn = ROW_NUMBER() OVER
            (
                PARTITION BY ddi
                ORDER BY ddi, StartTime DESC
            )
        FROM InboundCallsView
    )
SELECT *
FROM ddiWithRowNumber
WHERE rn = 1

Обратите внимание, что с помощью этого метода вам не нужно присоединять базовый вид / таблицу к промежуточному CTE.

Вы можете проверить производительность каждого метода, чтобы увидеть, какой из них лучше для вас.

...