Вы можете использовать LAG и LEAD для этого, но это немного утомительно, если у вас много столбцов. Вместо этого попробуйте:
WITH cte AS(
SELECT *, ROW_NUMBER() OVER(ORDER BY post_CreatedOn) rn
FROM posts
WHERE
post_createdOn < :date AND
post_isLog = 1 AND
post_live = 1
)
SELECT *
FROM
cte curr
LEFT JOIN cte next ON curr.rn+1 = next.rn
LEFT JOIN cte prev ON curr.rn-1 = prev.rn
Кажется, вы не указываете ни одного раздела - вы просто говорите, что ваша таблица представляет собой один длинный поток датированных записей, и у каждой записи есть предыдущий и следующий по дате. Если есть какое-то представление о том, что группы столбцов принадлежат друг другу, поместите объект, который группирует их в номер строки, как PARTITION BY, а также добавьте его в предложения ON для соединения между prev curr и next
I ' Мне не совсем ясно, хотите ли вы «следующую» строку, если она выходит за пределы даты. Например, если у вас есть две строки 2000-12-31 и 2001-01-01, и вы установили свой параметр даты на 2001-01-01, то более поздняя запись будет исключена как "текущая", но означает ли это, что 2000-12- 31 строка должна иметь значение «next», равное нулю, или это строка 2001-01-01
Если необходимо (этот запрос не вернет его), возьмите предикат из CTE и поместите его в основной запрос ГДЕ, вместо curr.post_createdOn
Если вы создаете какую-то систему разбиения на страницы, с одним журналом в день и вам нужно 3 строки, рассмотрите:
WITH cte AS(
SELECT *
FROM posts
WHERE
post_isLog = 1 AND
post_live = 1
)
SELECT. *
FROM cte
WHERE post_createdOn IN(
SELECT MAX(post_createdOn) FROM cte WHERE post_createdOn < @date
UNION ALL
SELECT @date
SELECT MIN(post_createdOn) FROM cte WHERE post_createdOn > @date
)