Как получить id следующей записи?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Arroyo
Сообщения: 105
Зарегистрирован: 2014.11.29, 11:24

Как получить id следующей записи?

Сообщение Arroyo »

Мне нужно получить ID следующей по дате записи, но если дата следующей записи такая же как у предыдущей, то запись пропускается.
Если написать "<=" то будет возвращать тот же ID.

Подскажите как правильно это написать?

Вот мой код:

Код: Выделить всё

    
    public function getNextId()
    {
        $record = $this->find()
            ->where(['<', 'created_at', $this->created_at])
            ->orderBy('created_at DESC')
            ->one();
            
        if($record !== null)
            return $record->id;
            
        return null;
    }
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Как получить id следующей записи?

Сообщение Alexum »

ID у вас автоинкремент? В таком случае дата вам не помошник, ориентируйтесь только на ID записи. Логично предположить, что id следующей записи будет больше на 1, но такая запись может быть удалена, поэтому придётся смотреть на все записи с id больше текущего и выбирать наименьший.

Код: Выделить всё

public function getNextId()
    {
        $record = $this->find()
            ->where(['>', 'id', $this->id])
            ->limit(1)
            ->orderBy(['id' => SORT_ASC])
            ->one();
            
        if($record !== null){
            return $record->id;
        }
        return null;
}
только логичнее сразу вытащить минимальное значение, незачем всю запись тягать.

Код: Выделить всё

$next_id = $this->find()->where(['>', 'id', $this->id])->min('id')
Arroyo
Сообщения: 105
Зарегистрирован: 2014.11.29, 11:24

Re: Как получить id следующей записи?

Сообщение Arroyo »

Спасибо. Но у меня сортировка именно по дате и она не совпадает с сортировкой по ID, т.к. дата может быть любой, установленной вручную.
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Как получить id следующей записи?

Сообщение Alexum »

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

Код: Выделить всё

public function getNextId()
    {
        $record = $this->find()
            ->limit(1)
            ->where(['>', 'id', $this->id])
            ->orderBy(['created_at' => SORT_ASC,'id' => SORT_ASC])
            ->one();
            
        if($record !== null){
            return $record->id;
        }
        return null;
}
Т.е. сперва сортируем по дате, затем по ID. Таким образом записи в разрезе одного дня будут хотя бы выстроены по id (иметь фиксированную последовательность). Конечно в вашем варианте они будут стоять не в порядке их реального добавления, но перейти на следующую запись получится.
Arroyo
Сообщения: 105
Зарегистрирован: 2014.11.29, 11:24

Re: Как получить id следующей записи?

Сообщение Arroyo »

Alexum писал(а): 2017.01.26, 16:05 Тогда у вас проблемы, ибо по какой логике должна определяться последовательность? С таким подходом единственное, что приходит в голову:

Код: Выделить всё

public function getNextId()
    {
        $record = $this->find()
            ->limit(1)
            ->where(['>', 'id', $this->id])
            ->orderBy(['created_at' => SORT_ASC,'id' => SORT_ASC])
            ->one();
            
        if($record !== null){
            return $record->id;
        }
        return null;
}
Т.е. сперва сортируем по дате, затем по ID. Таким образом записи в разрезе одного дня будут хотя бы выстроены по id (иметь фиксированную последовательность). Конечно в вашем варианте они будут стоять не в порядке их реального добавления, но перейти на следующую запись получится.
Что-то не сработала такая система. Сделал так:

Код: Выделить всё

    public function getNextId()
    {
        $record = $this->find()
            ->where(['<=', 'created_at', $this->created_at])
            ->andWhere(['status' => self::STATUS_ACTIVE])
            ->orderBy(['created_at' => SORT_DESC])
            ->all();
            
        foreach($record as $i => $r)
           if($r->id == $this->id)
              return isset($record[$i+1]->id) ? $record[$i+1]->id : NULL;
            
        return null;
    }
Только теперь выбирает все записи.
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Как получить id следующей записи?

Сообщение Alexum »

Arroyo писал(а): 2017.01.26, 17:38 Что-то не сработала такая система...
Просто интересно, что именно не сработало? Какой id возвращает?
Nerf
Сообщения: 780
Зарегистрирован: 2015.01.29, 00:37

Re: Как получить id следующей записи?

Сообщение Nerf »

Тянуть все записи из БД, создавать экземпляры AR для всех ради одно записи - идеальное решение. Подход с ID - верный.
Arroyo
Сообщения: 105
Зарегистрирован: 2014.11.29, 11:24

Re: Как получить id следующей записи?

Сообщение Arroyo »

Alexum писал(а): 2017.01.26, 18:04
Arroyo писал(а): 2017.01.26, 17:38 Что-то не сработала такая система...
Просто интересно, что именно не сработало? Какой id возвращает?
Этот способ пропускает ID с одинаковыми датами

PS Хотя нет. он пропустил потому что ID меньше, а дата выставлена выше. потому мне и нужна сортировка именно по дате.
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Как получить id следующей записи?

Сообщение caHek2x »

хм перечитал два раза..
да ид не берем во внимание т.к. как я понял у вас есть вариант редактирования даты ...
и почему вы знак больше/меньше не в ту сторону ставите ?
если я вас правильно понял если запись например 01.15.2017 то следующая в вашем понимании 02.15.2017 ... ?
тогда сортировка почему вы вытаскиваете с максимальной датой (SORT_DESC) .. ? вам разве самая новая по дате запись нужна ? или следующая по дате после вашей ?
что в таком варианте не так: ?

Код: Выделить всё

    public function getNextId()
    {
        $record = $this->find()
            ->where(['>', 'created_at', $this->created_at])
            ->andWhere(['status' => self::STATUS_ACTIVE])
            ->orderBy(['created_at' => SORT_ASC])
            ->one();
        return $record?$record->id:NULL;
    }
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Как получить id следующей записи?

Сообщение Alexum »

caHek2x писал(а): 2017.01.26, 19:26 да ид не берем во внимание т.к. как я понял у вас есть вариант редактирования даты ...
Если id совсем не учитывать, тогда в его случае последовательность записей будет определяться только их физическим положением.
caHek2x писал(а): 2017.01.26, 19:26 что в таком варианте не так: ?

Код: Выделить всё

    public function getNextId()
    {
        $record = $this->find()
            ->where(['>', 'created_at', $this->created_at])
            ->andWhere(['status' => self::STATUS_ACTIVE])
            ->orderBy(['created_at' => SORT_ASC])
            ->one();
        return $record?$record->id:NULL;
    }
В БД могут быть несколько записей с одинаковой датой, т.е. запрос не захватит другую запись с той же датой. Я предложил на мой взгляд рабочий вариант, но у ТСа какие-то трудности возникли. И вот это "->andWhere(['status' => self::STATUS_ACTIVE])" откуда-то появилось, Это у вас случаем не таблица User?
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Как получить id следующей записи?

Сообщение caHek2x »

да смотрю ваш вариант, ну только раз у него id может быть любой у даты .. .то есть:
1 - 01.15.2017
2 - 01.17.2017
3 - 01.14.2017
4 - 01.14.2017
если текущая запись 4 то следующая должна быть или 3 или 1 ... но условие где id>4 не прокатит ...

поэтому сортировка пусть идет по дате, + сортировка как вы и советовали еще и по id если даты одинаковые ... и на всякий случай != текущий ид ...
итого:

Код: Выделить всё

            ->where(['>=', 'created_at', $this->created_at])
            ->andWhere(['!=', 'id', $this->id])
            ->orderBy(['created_at' => SORT_ASC,'id' => SORT_ASC])
но если даты одинаковые то этот вариант не прокатит т.к. просто тупо зациклится между двумя записями ...
ничего не поделать, разве что костыль, как и сделал ТС, вытаскивать все записи больше или равные его ... и в цикле перебирать .... только отказаться бы там от моделей ... а сделать ->asArray и select(['id'])

интуиция внутри меня подсказывает что у ТС НЕ одинаковые даты ... я боюсь он как то не так выразился ... может после обработки форматером они выглядят одинаково на на самом деле секунды отличаются всеже ... смотря в чем дату хранит ...
Arroyo
Сообщения: 105
Зарегистрирован: 2014.11.29, 11:24

Re: Как получить id следующей записи?

Сообщение Arroyo »

caHek2x писал(а): 2017.01.26, 19:26 хм перечитал два раза..
да ид не берем во внимание т.к. как я понял у вас есть вариант редактирования даты ...
и почему вы знак больше/меньше не в ту сторону ставите ?
если я вас правильно понял если запись например 01.15.2017 то следующая в вашем понимании 02.15.2017 ... ?
тогда сортировка почему вы вытаскиваете с максимальной датой (SORT_DESC) .. ? вам разве самая новая по дате запись нужна ? или следующая по дате после вашей ?
что в таком варианте не так: ?

Код: Выделить всё

    public function getNextId()
    {
        $record = $this->find()
            ->where(['>', 'created_at', $this->created_at])
            ->andWhere(['status' => self::STATUS_ACTIVE])
            ->orderBy(['created_at' => SORT_ASC])
            ->one();
        return $record?$record->id:NULL;
    }
Ну да, все верно, у себя то я поменял на знак меньше и сортировку DESС.
Alexum писал(а): 2017.01.26, 19:38 И вот это "->andWhere(['status' => self::STATUS_ACTIVE])" откуда-то появилось, Это у вас случаем не таблица User?
Нет. Но разве эта строчка что-то для нас меняет? я ее из примера убирал, чтоб меньше лишнего кода было.
caHek2x писал(а): 2017.01.26, 20:36 интуиция внутри меня подсказывает что у ТС НЕ одинаковые даты ... я боюсь он как то не так выразился ... может после обработки форматером они выглядят одинаково на на самом деле секунды отличаются всеже ... смотря в чем дату хранит ...
Да, даты одинаковые по секундам :) timestamp
Ответить