Найти запись старше / новее текущей записи в SQL - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь написать оператор SQL, который дает мне предыдущую / следующую запись.

В моей таблице сообщений есть записи, которые являются либо сообщением блога, либо журналом кораблей (на основе столбца posts_isLog, являющегося либо 1, либо 0).

Я использую следующую подготовленную инструкцию для возврата текущего журнала кораблей на основе даты. Столбец post_createdOn является типом данных даты / времени. Я использую оператор like, чтобы сопоставить пройденную дату с запросом, так как он находится по URL-адресу, например «shiplog / 14th-April-2020». Дата изменена в соответствии с данными, поэтому гггг-мм-дд, так что никаких проблем нет.

//query
$this->db->query('SELECT * 
                  from posts 
                    INNER JOIN voyages ON posts.post_voyage = voyages.voyage_id 
                  WHERE post_createdOn LIKE :date 
                  AND post_isLog = 1 
                  AND post_live = 1');
//bind values
$this->db->bind(':date', '%'.$date.'%');
//get the results
$row = $this->db->single();
return $row;

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

Я думаю, что я хочу написать что-то вроде ... "Выбрать все из сообщений, где post_createdOn меньше, чем дата post_createdOn текущей записи".

Я пытаюсь

//query
$this->db->query('SELECT * 
                  from posts 
                  WHERE post_createdOn < :date 
                    AND post_isLog = 1 
                    AND post_live = 1');
//bind values
$this->db->bind(':date', '%'.$date.'%');
//get the results
$row = $this->db->single();
return $row;

Но я знаю, что это не относится к текущей записи. Полностью озадачен!

Это реферинг $this->db->single();

//get single record as an object
    public function single() {
      $this->execute();
      return $this->statement->fetch(PDO::FETCH_OBJ);
    }

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Спасибо за все ответы!

Кажется, я был почти там после помощи @ RiggsFolly. Я вынул% и запрос вернул результат. Мне нужно было упорядочить результаты, так как я возвращал только первый ряд!

public function getPreviousLog($date) {
    //query
    $this->db->query('SELECT * 
                      from posts 
                      WHERE post_createdOn < :date 
                      AND post_isLog = 1 
                      AND post_live = 1 
                      ORDER BY post_createdOn DESC');
    //bind values
    $this->db->bind(':date', $date);
    //get the results
    $row = $this->db->single();
  }
0 голосов
/ 15 апреля 2020

Вы можете использовать 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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...