Comments 45
На framework.zend.com/manual/en/zend.db.select.html
есть пункт 15.4.3.5. Adding Another Table to the Query with JOIN
есть пункт 15.4.3.5. Adding Another Table to the Query with JOIN
А где вы там нашли, что можно задавать не имя таблицы строкой, а переменную типа Zend_Db_Select?
Ой а это гдето в другом месте есть :) Там сказано примерно следующее: Zend_Db_Select есть магический __toString() который и превращает обьект запроса в строку.
Но вот с вложенными запросами — это прикольно. Все время писал raw-sql. Спасибо!
Но вот с вложенными запросами — это прикольно. Все время писал raw-sql. Спасибо!
Это есть в исходниках. А вы разве не читаете исходники ZF на ночь??? :)
Шутки-шутками, а это точно, что в исходниках есть намного больше, чем в мануалах и апи. Правда не стоит начинать сразу с них, если только почитать больше нечего =).
О! Может вы мне подскажете?
Как с помощью Zend_Db_Select сделать «SELECT SQL_CALC_FOUND_ROWS DISTINCT»?
Мне нужно знать количество удовлетворяющих условию строк для пагинатора, чтобы он мог расчитать количество страниц.
Как с помощью Zend_Db_Select сделать «SELECT SQL_CALC_FOUND_ROWS DISTINCT»?
Мне нужно знать количество удовлетворяющих условию строк для пагинатора, чтобы он мог расчитать количество страниц.
Zend_Db_Expr вас спасет, по идее
А можно работающий пример? Вот чтобы именно так, в таком порядке, перед перечислением полей?
Оно?
==>
$select->from('TableName' ,array(
new Zend_Db_Expr('SQL_CALC_FOUND_ROWS DISTINCT *'),
'row2',
'row3'
));
echo $select;
==>
SELECT SQL_CALC_FOUND_ROWS DISTINCT *, `TableName`.`row2`, `TableName`.`row3` FROM `TableName`
Ага, оно, но больше похоже на грязный хак.
Да и какой смысл использовать Zend_Db_Select, если половину запроса всё равно приходится писать в «сыром» виде в конструкторе дополнительного объекта?
Добавьте сюда ещё невозможность конструирования сложных WHERE-условий, которые тоже приходится вписывать в сыром виде типа
Проще уж обычной строкой.
Да и какой смысл использовать Zend_Db_Select, если половину запроса всё равно приходится писать в «сыром» виде в конструкторе дополнительного объекта?
Добавьте сюда ещё невозможность конструирования сложных WHERE-условий, которые тоже приходится вписывать в сыром виде типа
->where('((A or (B and C)) and D) or E)')
.Проще уж обычной строкой.
Ну учитывая что SQL_CALC_FOUND_ROWS врятли найдеться в спицификации SQL (хотя я не уверен;), то хак на хаке :)
dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_found-rows
:)
«LIMIT» тоже не везде есть, но в Zend_Db_Select он поддерживается.
:)
«LIMIT» тоже не везде есть, но в Zend_Db_Select он поддерживается.
Для Oracle в Zend определен свой специфический LIMIT (тоже хак, кстати). Так что это они поддерживают. Дело не в стандартах, а в том, насколько часто та или иная фишка используется программистами.
Интересно, через псевдостолбец и группировку или как-то красивей сделали…
Я помню, так и не смог сделать этот LIMIT (ещё в «дозендовские» времена), просто забил, так как размер таблицы теоретически не мог превысить даже тысячи записей (на деле около сотни) — фетчил все строки до лимита, т.е. если limit 10, то только первые десять строк, а если Limit с 100 по 110, то 110 строк, игнорируя ненужные. Для последней страницы, соответственно, приходилось выбирать всю таблицу :)
Я помню, так и не смог сделать этот LIMIT (ещё в «дозендовские» времена), просто забил, так как размер таблицы теоретически не мог превысить даже тысячи записей (на деле около сотни) — фетчил все строки до лимита, т.е. если limit 10, то только первые десять строк, а если Limit с 100 по 110, то 110 строк, игнорируя ненужные. Для последней страницы, соответственно, приходилось выбирать всю таблицу :)
Дык может и SQL_CALC_FOUND_ROWS будет как-то поддерживаться. А пока можно расширить класс для себя, добавив свою константу следующим образом:
Не проверил работоспособность, но логика правильная.
class My_Db_Select extends Zend_Db_Select
{
const SQL_CALC_FOUND_ROWS = 'sql_calc_found_rows';
public function __construct(Zend_Db_Adapter_Abstract $adapter)
{
self::$_partsInit = array_merge(array(
self::SQL_CALC_FOUND_ROWS => false
), self::$_partsInit);
parent::__construct($adapter);
}
public function calcFoundRows($flag)
{
$this->_parts[self::SQL_CALC_FOUND_ROWS] = (bool)$flag;
return $this;
}
}
* This source code was highlighted with Source Code Highlighter.
Не проверил работоспособность, но логика правильная.
Спасибо за код :)
Ага, я думал об этом, но мне былолень жаль тратить время ради одного запроса. Хотя в этом чате я уже потратил его больше :)
Ага, я думал об этом, но мне было
Как-то странно получилось.
Сперва (давно) всё работало, а сегодня вдруг перестало.
Нужно добавить вот такой метод:
protected function _renderSql_calc_found_rows($sql)
{
if ($this->_parts[self::SQL_CALC_FOUND_ROWS]) {
$sql .= ' '. self::SQL_CALC_FOUND_ROWS;
}
return $sql;
}
Сперва (давно) всё работало, а сегодня вдруг перестало.
Нужно добавить вот такой метод:
protected function _renderSql_calc_found_rows($sql)
{
if ($this->_parts[self::SQL_CALC_FOUND_ROWS]) {
$sql .= ' '. self::SQL_CALC_FOUND_ROWS;
}
return $sql;
}
Ну это скорее не грязный хак, а просто отвод для пока неподдерживаемых вещей. Но другого пути я тоже не знаю.
> ->where('((A or (B and C)) and D) or E)')
Кстати, можно раскрыть скобки (A and D or B and C and D or E) и записать при помощи соответствующих методов:
Получим:
Приоритеты операций — наше всё =)
Кстати, можно раскрыть скобки (A and D or B and C and D or E) и записать при помощи соответствующих методов:
$query = $db->select()
->from('test')
->where('A')
->where('D')
->orWhere('B')
->where('C')
->where('D')
->orWhere('E');
echo $query->assemble();
* This source code was highlighted with Source Code Highlighter.
Получим:
SELECT `test`.* FROM `test` WHERE (A) AND (D) OR (B) AND (C ) AND (D) OR (E)
* This source code was highlighted with Source Code Highlighter.
Приоритеты операций — наше всё =)
Чёрт.
Ты прав :)
Но после раскрытия скобок логика условия уже не такая явная.
Допустим, А — это проверка авторизации (прав на просмотр), а ВCDE — это уже какие-то условия выборки, то:
если у меня было «A and (B or C or D or E)», то получится «A and B or A and C or A and D or A and E». И через месяц долго будешь втыкать в этот столбик
А условий может быть больше и вложенность глубже :)
Ты прав :)
Но после раскрытия скобок логика условия уже не такая явная.
Допустим, А — это проверка авторизации (прав на просмотр), а ВCDE — это уже какие-то условия выборки, то:
если у меня было «A and (B or C or D or E)», то получится «A and B or A and C or A and D or A and E». И через месяц долго будешь втыкать в этот столбик
->where(B)
->where(A)
->orWhere(С)
->where(A)
->orWhere(D)
->where(A)
->orWhere(E)
->where(A)
А условий может быть больше и вложенность глубже :)
Я полностью согласен, что ясность теряется абсолютно. Просто задумался… все основные логические операции введены и не может так получаться, что какое-то условие реализовать нельзя. =)
Понятно, что полумера, но:
//A and (B or C or D or E)
->where(B)
->where(A)
->orWhere(С)
->where(A)
->orWhere(D)
->where(A)
->orWhere(E)
->where(A)
? :)
//A and (B or C or D or E)
->where(B)
->where(A)
->orWhere(С)
->where(A)
->orWhere(D)
->where(A)
->orWhere(E)
->where(A)
? :)
Если посмотреть в тикеты зенда то можно увидеть что в ближайшем будущем планируется переделать where так чтобы он принимал массив.
и без запятых!
Для вас самый простой способ
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
echo $adapter->count();
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
echo $adapter->count();
А как это работает на деле?
Выполняется дополнительный запрос '
Выполняется дополнительный запрос '
select count(*)
'?упрощенно — да
Ну, я, по сути, так и делал сперва, сперва вызов текущей страницы с «LIMIT», потом count(*) для подсчёта страниц, и потом именно для ускорения работы переделал на «SQL_CALC_FOUND_ROWS», чтобы сервер два раза за одним запросом не гонять :)
И много выиграли в производительности =)?
Экономите на спичках :) Запрос конечно дело тяжёлое для системы, но время потраченное на лишние строки кода, можно потратить на что-либо более существенное.
Да простятся мне грехи мои.
Я использую Postrge и твёрдо веровал в силу Zend_Db пока не пришёл к
select
a,
b,
array_to_string(
array(
ещё один запрос
),
','
) as с
from
table name
where
where clause
Пока не знаю как тут поступить.
Я использую Postrge и твёрдо веровал в силу Zend_Db пока не пришёл к
select
a,
b,
array_to_string(
array(
ещё один запрос
),
','
) as с
from
table name
where
where clause
Пока не знаю как тут поступить.
Жесть, у нас за такие запросы — расстрел на месте.
Ну до этого все понимали, что я просто привёл пример вложенного запроса. Или у вас всегда расстреливают за них вне зависимости от того увеличивают они быстродействие или нет? =)
Sign up to leave a comment.
Вложенные запросы при помощи Zend_Db_Select