Сделайте выбор с максимальным и минимальным условием прохождения для каждого из двух

При доступе к сообщению мне нужно, помимо возврата информации об этом сообщении, вернуть предыдущий, если он существует, и следующий.

Я хотел бы знать, есть ли способ выбрать MAX(id) и MIN(id) в одном запросе/выборе, передав условие для каждого из них. Пример того, что я пытаюсь сделать в Laravel, и я напишу это на SQL, чтобы упростить задачу.

Ларавель:

$query = Post::query();
$query = $query->from('posts')->select(DB::raw('MAX(id), MIN(id)'))->whereRaw("id < {$id} and id > {$id}")->first();

SQL:

select MAX(id), MIN(id) from `posts` where id < 5 and id > 5 limit 1

Переменная id — это значение идентификатора сообщения. В этом примере он имеет значение 5. Я делаю запрос, чтобы получить MAX и MIN, относящиеся к этому идентификатору, но мне также нужно получить информацию о публикации, к которой обратился пользователь.

В БД есть пост id номер 4 и номер 6. То есть мне нужно получить информацию из постов номер 4, 5 и 6 в этом примере.

Условие where никогда не будет true, но я не могу использовать or. Первое условие для MAX, а второе для MIN. Если я использую or, самый большой идентификатор будет получен из БД.

Мне нужно получить минимальное и максимальное значение по сравнению со значением. То есть, как я объяснил выше. Если id равен 5, мне нужно получить самый большой существующий id() ниже этого значения, и мне нужно получить наименьшее значение над ним. В моем случае из информации, которая есть у меня в БД, это будут идентификаторы 4, 5 и 6.

Возможно ли это за одну консультацию или мне действительно нужно сделать больше одной?

id < 5 and id > 5 никогда не бывает ИСТИННЫМ.
jarlh 15.02.2023 14:08

Да, но я не могу использовать or. Первое условие для MAX, а второе для MIN. Если я использую or. Самый большой идентификатор будет исходить из БД

Gabriel Edu 15.02.2023 14:10

минимальный воспроизводимый пример сделал бы это намного яснее.

jarlh 15.02.2023 14:11

Я не знаю, как быть яснее. Мне нужно получить минимальное и максимальное значение по сравнению со значением. То есть, как я объяснил выше. Если id равен 5, мне нужно получить самый большой существующий id() ниже этого значения, и мне нужно получить наименьшее значение над ним. В моем случае из информации, которая есть у меня в БД, это будут идентификаторы 4, 5 и 6.

Gabriel Edu 15.02.2023 14:14

Образец табличных данных и ожидаемый результат - все в виде форматированного текста (без изображений, без ссылок).

jarlh 15.02.2023 14:15
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
6
5
231
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Функции LEAD() и LAG() в MySQL используются для получения предыдущего и последующего значения любой строки в ее разделе.

Попробуй это:

  SELECT ID,
         LAG (id) OVER (ORDER BY NULL) ONE_SHIFT_FORWARD,
         LEAD (id) OVER (ORDER BY NULL) ONE_SHIFT_BACKWARD
    FROM POSTS
ORDER BY ID ASC;

SELECT *
  FROM (  SELECT ID,
                 LAG (id) OVER (ORDER BY NULL) ONE_SHIFT_FORWARD,
                 LEAD (id) OVER (ORDER BY NULL) ONE_SHIFT_BACKWARD
            FROM POSTS
        ORDER BY ID ASC)
 WHERE id = 5;

Очень хорошо, в SQL это работает, но в Laravel я не смог воспроизвести это. Я исследовал, тестировал, но таким образом выдает ошибку «ASC или DESC». Но большое спасибо за альтернативу.

Gabriel Edu 15.02.2023 14:51

Попробуйте удалить слово ASC. Только писать: ORDER BY ID (без слова ASC, что означает ПО ВОЗРАСТУ).

UltraCommit 15.02.2023 16:02
Ответ принят как подходящий

Да, вы можете сделать это с case-when

select MAX(
           CASE
               WHEN id < 5 THEN id
               ELSE NULL
           END
       ), MIN(
           CASE
               WHEN id > 5 THEN id
               ELSE NULL
           END
       )
from `posts` 
where id <> 5

РЕДАКТИРОВАТЬ

Эквивалент Laravel, как поделился Габриэль Эду в разделе комментариев:

$query = Post::query();
$query = $query->from('posts')->
         select(DB::raw("MAX(CASE WHEN id < {$id} THEN id ELSE null END), MIN(CASE WHEN id > {$id} THEN id ELSE null END)"))->first(); 

Очень хорошо, но я этого не знал. Это очень помогло. Так как это для Laravel, я добавлю его сюда, чтобы помочь кому-то еще. КОД: $query = Post::query(); $query = $query->from('posts')->select(DB::raw("MAX(CASE WHEN id < {$id} THEN id ELSE null END), MIN(CASE WHEN id > {$id} THEN id ELSE null END)"))->first();

Gabriel Edu 15.02.2023 14:34

@GabrielEdu спасибо за кусок кода Laravel, добавил его в мой ответ. Если этот ответ решил вашу проблему, вы можете принять его как правильный ответ.

Lajos Arpad 15.02.2023 14:38

Я думаю, что предложение LIMIT 1 может быть удалено из запроса.

UltraCommit 15.02.2023 16:09

@UltraCommit да, ваше наблюдение верно, удалил его.

Lajos Arpad 15.02.2023 16:10

Вы можете использовать lead и lag для доступа к значениям до и после текущей строки. Затем вы можете использовать их для выбора сообщения с заданным идентификатором и значениями до и после в одном выборе.

Следующий запрос

select * 
    from (
    select 
        p.*,
        lead(id) over(order by id) _lead,
        lag(id) over(order by id) _lag
    from post p
) x
where 23 in (id, _lead, _lag);

приводит к

идентификатор текст _вести _лаг 15 пятнадцать 23 10 23 двадцать три 24 15 24 двадцать четыре 50 23

Со следующей настройкой:

Схема (MySQL v8.0)

create table post (
    id integer,
    text varchar(50)
);
    
insert into post(id, text)
values
( 10, 'ten'),
( 15, 'fifteen'),
( 23, 'twentythree'),
( 24, 'twentyfour'),
( 50, 'fifty');

Посмотреть на DB Fiddle

Очень хорошо, в SQL это работает, но в Laravel я не смог воспроизвести это. Я исследовал, тестировал, но таким образом выдает ошибку «ASC или DESC». Но большое спасибо за альтернативу.

Gabriel Edu 15.02.2023 14:50

Другие вопросы по теме