SQL-запрос для извлечения записей из каждой группы таблицы

#sql #sql-server

#sql #sql-сервер

Вопрос:

Данные таблицы, как показано ниже:

Содержимое таблицы

Вывод должен быть следующим:

вывод данных таблицы

Условия:

  1. Извлеките первую и последнюю строки из каждой группы.
  2. Если значение col4 равно «A» в первой строке, в этом случае вместе с первой и последней строкой извлеките также 2-ю строку.

Есть ли способ выполнить это с помощью простого SQL-запроса, используя какие-либо конкретные аналитические функции в Microsoft SQL Server?

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

1. Несколько быстрых вопросов, на которые можно ответить: есть ли у таблицы первичный ключ (и это просто произвольный идентификатор в начале или Col1 Col3)? По ‘first’, ‘second’ и ‘last’, как они упорядочены — по временному полю ‘col2’ или по ‘col3’? И для заданного значения Col1 у вас могут быть дубликаты в col2, например, вторая строка в таблице, которая также имеет col1 = 1 и col2 = 10/9/2020 17:11?

2. Col1 является первичным ключом, они упорядочены по Col1 asc и Col2 desc, да, для заданного значения Col1 у нас могут быть дубликаты в col2, например, вторая строка в таблице, которая также имеет col1 = 1 и col2 = 10/9/2020 17:11, большое спасибо за ваш ответ и за вопросэти вопросы

3. Я не думаю, что Col1 может быть PK — у него есть дубликаты. Приведенный ниже ответ @Gordon хорош, но вы можете также указать, как определить, о какой строке вы хотите сообщить, если у вас есть эти дублирующиеся строки (для этого потребуется просто изменить инструкции ORDER BY в оконных функциях).

4. Спасибо seanb, да, Col1 является первичным ключом какой-либо другой таблицы, он не является первичным ключом в этом наборе результатов, здесь, во входной таблице, я показываю набор результатов, полученный после выполнения некоторых соединений между разными таблицами.

5. Все в порядке, ответ PK — @Gordon в этом не нуждается. Однако дубликаты Col1 / Col2 являются потенциальной проблемой.

Ответ №1:

Хммм … для этого можно использовать оконные функции:

 select t.*
from (select t.*,
             first_value(col4) over (partition by col1 order by col2) as first_col4,
             row_number() over (partition by col1 order by col2) as seqnum_asc,
             row_number() over (partition by col1 order by col2 desc) as seqnum_desc
      from t
     ) t
where seqnum_asc = 1 or seqnum_desc = 1 or
      (seqnum_asc = 2 and first_col4 = 'a');
  

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

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

1. Спасибо за запрос, не могли бы вы, пожалуйста, объяснить мне работу этого запроса, чтобы в будущем я мог думать в этом направлении.