#sql #sql-server
#sql #sql-сервер
Вопрос:
Данные таблицы, как показано ниже:
Вывод должен быть следующим:
Условия:
- Извлеките первую и последнюю строки из каждой группы.
- Если значение 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. Спасибо за запрос, не могли бы вы, пожалуйста, объяснить мне работу этого запроса, чтобы в будущем я мог думать в этом направлении.