Пропускать количество строк на основе значения одного столбца с использованием ROW_NUMBER

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

Я использую ROW_NUMBER(), чтобы упорядочить количество раз, когда определенный код используется для каждого идентификатора посещения. Ниже приведена измененная часть запроса для примера.

  SELECT
    ROW_NUMBER() OVER (PARTITION BY VisitID ORDER BY EventActualDateTime) AS 'RowNum'
    ,VisitID
    ,EventActualDateTime
    ,Code
    ,LocationID
FROM
    AdmVisitEvents
WHERE
    VisitID = '6012227281'
     and Code IN ('ENADMIN','TFRADMIN')
  

введите описание изображения здесь

Я пытаюсь найти способ исключить СТРОКУ, если LocationID совпадает с предыдущей строкой.

Итак, мой результирующий набор должен выглядеть следующим образом:

введите описание изображения здесь

Это могло произойти и ранее при подсчете строк. Например, если бы первый код TFRADMIN имел тот же LocationID, что и код ENADMIN *, мне нужно было бы также пропустить эту строку. (*Коды ‘ENADMIN’ или ‘OBSVTOIN’ всегда будут строкой 1, а СТРОКА 2 всегда будет кодом ‘TFRADMIN’).

Итак, другим примером может быть:

введите описание изображения здесь

Если это был мой результат, он должен показывать только:

введите описание изображения здесь

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

1. Какую версию SQL-Сервера вы используете?

2. SQL Server 2016

Ответ №1:

Это непроверено из-за отсутствия пригодных для использования образцов данных (изображение не пригодно для использования, поскольку единственный способ, которым добровольцы могут его использовать, — это моя расшифровка), однако, LAG должно помочь вам достичь этого:

 WITH CTE AS
    (SELECT VisitID,
            EventActualDateTime,
            Code,
            LocationID,
            LAG(LocationID) OVER (PARTITION BY VisitID ORDER BY EventActualDateTime) AS PreviousLocationID
     FROM AdmVisitEvents
     WHERE VisitID = '6012227281'
       AND Code IN ('ENADMIN', 'TFRADMIN'))
SELECT ROW_NUMBER() OVER (PARTITION BY VisitID ORDER BY EventActualDateTime) AS RowNum,
       VisitID,
       EventActualDateTime,
       Code,
       LocationID
FROM CTE
WHERE LocationID != PreviousLocationID OR PreviousLocationID IS NULL;
  

Обратите внимание, что PARTITION BY предложения на самом деле не нужны в этих запросах из-за вашего WHERE ( VisitID = '6012227281' ). Поскольку VisitID может иметь только одно скалярное значение, PARTITION BY никогда не будет генерироваться значений для другого «набора».

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

1. VisitID Было указано только для примера, оно будет удалено в полном запросе. Итак, мне действительно нужно partition by в конечном счете, я просто забыл удалить его здесь.

Ответ №2:

Вы можете использовать предложение row_number() with ties :

 SELECT TOP (1) WITH TIES VisitID, EventActualDateTime, Code, LocationID
FROM AdmVisitEvents
WHERE VisitID = '6012227281' AND 
      Code IN ('ENADMIN','TFRADMIN')
ORDER BY ROW_NUMBER() OVER (PARTITION BY VisitID, Code, LocationID  ORDER BY EventActualDateTime);