Предлагаю фичу, ну или как минимум дописать документацию.
В документации:
http://www.yiiframework.com/doc-2.0/yii-db-query.html
Написано:
between: operand 1 should be the column name, and operand 2 and 3 should be the starting and ending values of the range that the column is in. For example, ['between', 'id', 1, 10] will generate id BETWEEN 1 AND 10.
Можно ли сделать поддержку следующего?
$this->where(['between', $value, 'column_from', 'column_to'])->all();
Как я читал SQL подобную конструкцию поддерживает. MySQL поддерживает подобный синтаксис.
SELECT * FROM `mytable`
WHERE 4
BETWEEN `from` AND `to`
Так это же уже есть — https://github.com/yiisoft/yii2/blob/master/docs/guide/db-query-builder.md#operator-format-
Может тогда дописать строчку для тугодумов вроде меня =). Типа "ending values" может быть еще и columns.
@wartur кто ищет, тот найдет)
@kotchuprik @SilverFire Собственно не рабоатет, генерируется подобная конструкция
$this->select('id')->where(['BETWEEN', $duration, 'from', 'to'])->scalar();
SELECT `id` FROM `filter_duration` WHERE `3` BETWEEN 'from' AND 'to'
Вот результат:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '3' in 'where clause'
The SQL being executed was: SELECT `id` FROM `filter_duration` WHERE `3` BETWEEN 'from' AND 'to'
Error Info: Array
(
[0] => 42S22
[1] => 1054
[2] => Unknown column '3' in 'where clause'
)
Данная конструкция на SQL работает отлично
SELECT `id` FROM `filter_duration` WHERE '3' BETWEEN `from` AND `to`
читайте мануал, там вроде надо вначале колонки а потом значение
@lynicidn я знаю про мануал. Вы понимаете чего именно я хочу достигнуть?
Мне нужно поставить наоборот. Значение по двум другим колонкам. Очень удобная конструкция что бы не писать заумную альтернативу вроде
WHERE from >= 3 AND to <= 3
@wartur тут raw query как вариант юзать. Но про ваш кейс, надо смотреть как в других SQL базах работает) возможно это работает только в mysql
@kotchuprik Да, я сделал это через andFilterWhere([...])->andFilterWhere([...]), но все равно было бы круто если этот вариант можно было бы ввести. Я говорю рассмотрите вариант если будет времечко.
Но SQL (НЕ MySQL - а язык SQL) это точно поддерживает. Я уж не знаю какие там еще базы есть. Все же Yii2 достаточно сложный.
Мне нужно поставить наоборот. Значение по двум другим колонкам. Очень удобная конструкция что бы не писать альтернативу вроде
покажите запрос который вы хотите получить - он работает в вашем sql редакторе?
или вы сами придумываете синтаксис к sql а потом удивляетесь - почему уии2 его не понимает?
Но SQL (НЕ MySQL - а язык SQL) это точно поддерживает. Я уж не знаю какие там еще базы есть. Все же Yii2 достаточно сложный.
between ?
@lynicidn ну да http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt с 92 года как минимум =)
Я же написал что мне нужно
SELECT `id` FROM `filter_duration` WHERE '3' BETWEEN `from` AND `to`
оно же
SELECT `id` FROM `filter_duration` WHERE `from` => 3 AND `to` <= 3
Таблица следующая
from | to
0 | 1
2 | 2
3 | 3
4 | 7
8 |14
15 |21
22|30
При 3 я получаю запись 3|3
При 5 я получаю запись 4|7
При 25 я получаю запись 22|30
SQL как языку совершенно все равно значение подставляется или же колонка.
Да, это понятно. Я LIKE юзаю почти также. Слева строка, справа поле. Там так нужно :) Надо дождаться @samdark для ответа на этот ишью.
В данный момент я вижу только вариант выкручиваться через yii\db\Expression
, или писать это условие без билдера
@SilverFire возможно betweenColumn какой нить и там уже запрос строить <=, >=
В принципе, можно и запилить. between действительно поддерживается везде (конечно, стоит перепроверить).
И я бы с удовольствием реализовал, но непонятно, как это должно использоваться. Сейчас все операторы задаются так, как они выглядят в sql: 'NOT', 'AND', 'OR', 'BETWEEN', 'IN', 'LIKE', 'NOT LIKE', '>', '<=' и т.д.
Но если оставить оператор 'BETWEEN', нельзя будет определить, что надо использовать:
"$column BETWEEN $param1 AND $param2"
или
"$param BETWEEN $column1 AND $column2"
Если использовать что-то вроде $query->where(['BETWEEN COLUMN', $value, $column1, $column2]), то это будет выбиваться из общей схемы использования построителя запросов и будет слишком неочевидно для разработчиков.
['between', ['column1', 'column2'], $value]
@Vovan-VE @samdark Согласен, Хорошая конструкция
['between', ['column1', 'column2'], $value]
Как сделать тогда такой запрос?
SELECT * FROM table WHERE column1 BETWEEN column2 AND column3;
Тут по идее надо оставить ['between', 'column1', 'value1', 'value2']
, только привести к виду, чтобы работало: ['between', 'column1', 'column2', 'column3']
при чём:
'column1', 'column2', 'column3'
- может быть чем угодно, т.е. :
Да, задачка... причём когда мы передаём строку, не ясно, название ли это столбца или же значение.
я уже придумал, типа так:
[
['between', new Expression('3') , '[[from]]', '{{table}}.[[to]]'],
':qp0 BETWEEN [[id]] AND [[type]]',
[':qp0' => 3]
],
т.е. ['between', new Expression('3') , '[[from]]', '{{table}}.[[to]]'],
и получим
SELECT * WHERE 3 BETWEEN `from` AND `table`.`to`
пытаюсь набросать тестов и код... надо будет описать в доке ещё...
Господи... может быть забить на проблему проще? Реально проще просто пользоваться чем есть, чем тратить столько время над этой маленькой фичей. Предлагаю закрыть проблему и предлагать делать так: SELECT id
FROM table
WHERE from
=> 3 AND to
<= 3
Предлагаю делать так и не закрывать ничего:
['between', 'column1' , '[[column2]]', '{{table}}.[[column3]]']
Отличать значения от названий по скобочкам?
Ну это же общепринято http://www.yiiframework.com/doc-2.0/guide-db-dao.html#quoting-table-and-column-names. Только для первой оставить как есть. Т.е. если ['between', 'column1'
column1 всегда ожидается название колонки - иначе через Expression
Да, можно и так.
['between', 'column1' , '[[column2]]', '{{table}}.[[column3]]']
Да, можно и так.
Строго против, нельзя. У людей уже написано что-то в стиле
->andWhere(['between', 'date', $request->get('start-date'), $request->get('end-date')])
И получается, что мы создаём возможность крашнуть запрос, послав start-date=[[bla-bla]]
Если делать, то одобряю ['betweenColumns', $var , 'column1', 'column2']
(как предлагали выше), мне кажется проще, чем городить заумные универсальные конструкции. Это больше синтаксический сахар, чем конструкция которой пользуешься каждый день с большой гибкостью. Либо лучше не делать
Да, действительно...
И как ['betweenColumns', $var , 'column1', 'column2'],
она должна работать?
column1, column2- всегда только колонки?
А вдруг мне там надо значение вставить:
['betweenColumns', $var , 'column1', '9999'],
тогда опять возникает вопрос, как их различить с колонкой.
Предложенный мной вариант, опять приstart-date=[[bla-bla]]
приведёт к краху.
@githubjeka Да, только колонки. Либо экспрешоны, в которые можно фактически RAW код написать и слепить, что хочешь. Но в любом случае в случае лепки надо понимать, что получится монстр-конструкция. А нужен только синт. сахар для достаточно частой операции нахождения чего либо в промежутке. Честно в каждом проекте сталкивался в своей жизни поиск ID в диапазоне для постройки какого-то пользовательского индекса по списку. Думаю @samdark будет со мной согласен, что не надо универсалить там где это не надо, надо быть ближе к грешной земле.
Мне нравится ['betweenColumns', $var , 'column1', 'column2']
А вдруг мне там надо значение вставить:
new \yii\db\Expression()
Предложенный мной вариант, опять приstart-date=[[bla-bla]] приведёт к краху.
Как?
Как
Если это всегда колонки, то никак.
Остался вопрос с $var - это что? Колонка, значение или Expression ?
Значение. Как обычно, значение может быть представлено Expression'ом
Т.е. такой запрос -
SELECT * FROM table WHERE column1 BETWEEN column2 AND column3;
я опять не сделаю?
Короче пришли к такому:
['betweenColumns', 'column1' , 'column2', 'column3']
По умолчанию все всегда определяются как колонки, а если надо значения - они могут быть введены через Expression
По умолчанию все всегда определяются как колонки, а если надо значения - они могут быть введены через Expression
Да нет же. Зачем пользователя заставлять эскейпить строку вручную и засовывать ее в Expression?
Т.е. такой запрос -
SELECT * FROM table WHERE column1 BETWEEN column2 AND column3;
я опять не сделаю?
Сделаешь
['betweenColumns', new \yii\db\Expression('column1'), 'column2', 'column3']
А если я хочу так?
['betweenColumns', new \yii\db\Expression('{{%tableNameWithPrefix}}.[[column1]]'), 'column2', 'column3']
Хочешь - делай, в чём проблема то? :)
Если предлагаешь, что так себя будет вести новая betweenColumns, то предлагаю вернуться к варианту: ['between', ['column1', 'column2'], $value]
Тесты выглядят так и проходят:
| Команда | Ожидаемый результат |
| --- | --- |
[
['between', ['id', 'type'], 3],
':qp0 BETWEEN [[id]] AND [[type]]', [':qp0' => 3]
],
[
['between', ['id', 'type'], new Expression('column1')],
'column1 BETWEEN [[id]] AND [[type]]', []
],
[
['between', [new Expression(-120), 'type'], new Expression('column1')],
'column1 BETWEEN -120 AND [[type]]', [],
],
[
['between', [new Expression(-120), 'type'], '-9999'],
':qp0 BETWEEN -120 AND [[type]]', [':qp0' => -9999]
],
Там мутно в тестах сделано с параметрами ':qp0'...
, поэтому для этих тестов у меня сомнения насчёт ожидаемого результата. Если они верны, то я отправлю PR, проверьте пожалуйста.
Когда я хотел сделать ['between', ['id', 'type'], new Expression('{{table}}.[[column1]]')]
, вылезла эта штука REL #12676 , которую не просто победить....
Most helpful comment
['between', ['column1', 'column2'], $value]