Гловоломающая Регулярка

igortik

Новичок
Гловоломающая Регулярка

Стоит задача отправлять в объект один раз переменную $query, содержащую любой mysql-запрос.
Объект юзает функцию для обработки полученного ассоциативного массива, и, как приятное дополнение - должен отдать некий page_limiter (страничное разделение), т.е. мы не отправляем запрос еще раз, а сам метод объекта разбирает строку запроса и должен заменить первые SELECT ... FROM на SELECT count(*) FROM.

Все бы хорошо, и можно, на первый взгляд обойтись патерном SELECT .* FROM, но когда дело доходит до вложенных запросов, которые также в себе содержат SELECT.. FROM, например SELECT ... FROM .. WHERE `id`=(SELECT `id` FROM ...) и т.д. то начинаются пляски с бубном.

Я уже намучался с подбором вариантов и, потому прошу вашей помощи.
Сейчас стоит:

$query_count = preg_replace('/^SELECT (.++|\*)(\(.++FROM.++\))?(.++)? FROM/is','SELECT count(*) FROM',$this->query,1);

Также стоит учесть, что может быть банальный SELECT * FROM, которому подходит: .+

Этот пример выше $query_count подходит в 80% случаев ... но не подходит для иных вариантов.
Может кто решал подобного рода задачу, т.е. нам надо исключительно первые SELECT ... FROM заменить на SELECT count(*) FROM
 

igortik

Новичок
нед

-~{}~ 23.07.10 11:32:

Повторюсь:

Все бы хорошо, и можно, на первый взгляд обойтись патерном SELECT .* FROM, но когда дело доходит до вложенных запросов, которые также в себе содержат SELECT.. FROM, например SELECT ... FROM .. WHERE `id`=(SELECT `id` FROM ...) и т.д. то начинаются пляски с бубном.
 

igortik

Новичок
prolis
не подходит. $query отправляется один раз в полном виде, в таком, как должен быть запрос с селектом необходимых полей.

А вот задача page_limiter как раз обеспечить верный просчет страниц.

-~{}~ 23.07.10 16:42:

Welcome
Так модификатор g производит замену всех вхождений .......
 

Вурдалак

Продвинутый новичок
В PHP нет такого модификатора.

Надо делать два запроса, а не пытаться это автоматизировать. Либо, что мне не нравится, SQL_CALC_FOUND_ROWS.
 

igortik

Новичок
Вурдалак
точно, то для js ...

Ты считаешь, что все же решения нет?
Ведь вариантов-то не так много, по большому счету.

Просто нужно заменить первое вхождение SELECT ... FROM на наш SELECT count(*) FROM, дабы не было замены во вложенных запросах.
 

Вурдалак

Продвинутый новичок
igortik, я считаю, что этим не надо заниматься. Либо, как я уже сказал, SQL_CALC_FOUND_ROWS.

Кстати, preg_replace() имеет 4-й параметр.
 

igortik

Новичок
Вурдалак
я уже почти тоже так считаю, но остался один маневр для встряски мозгов.

Пример:

SELECT questions.*, (SELECT sum(`votes`) FROM `variants` WHERE variants.question_id = questions.id) as `votes` FROM `questions` WHERE `id`=(SELECT `id` FROM `questions` WHERE `id`=5)ORDER by `hide`,`name` DESC

не советую вникать в суть запроса а проанализировать желаемое в связке с регуляркой

$query_count = preg_replace('/^SELECT (\*|.+) FROM/is','SELECT count(*) FROM',$this->query);

Оно не подходит потому, что в данном случае FROM целяется полдений... это, в принципе и необходимо, чтобы по шаблону SELECT был первым, а FROM последним, но не в контексте, когда FROM болтается в ( ... ) ...

Как бы так описать, чтобы объяснить о том, что не учитывать патерн в том случае, когда FROM находится в круглых скобках ...
 

crocodile2u

http://vbolshov.org.ru
igortik
не занимайся ерундой. Составляй запросы нормально. Для того, что ты хочешь сделать, существуют конструкторы запросов типа Zend_Db_Select.
 

john.brown

просто кулибин
igortik
зря ты отмел вариант prolis. Может быть не понял, что он имел ввиду? как раз решает твою проблему, и без всяких регулярок

[sql]
SELECT COUNT(*) FROM (SELECT questions.*, (SELECT sum(`votes`) FROM `variants` WHERE variants.question_id = questions.id) as `votes` FROM `questions` WHERE `id`=(SELECT `id` FROM `questions` WHERE `id`=5)ORDER by `hide`,`name` DESC) AS `count_table`
[/sql]
 

igortik

Новичок
john.brown
мммм.... действительно... сейчас проверим!!!
Спасибо, большое.

crocodile2u
спасибо, учту

-~{}~ 23.07.10 20:25:

john.brown
все вроде хорошо.. но..

Ошибка: Duplicate column name 'id' В запросе: select count(*) from (SELECT news.*,news_content.* FROM `news` INNER JOIN `news_content` ON news.id = news_content.id WHERE `lang`='ru' ORDER by `date` DESC) as count

и так везде, где есть объединение таблиц и подобные вложенные запросы с повторяющимися именами полей
 

john.brown

просто кулибин
Ну так правильно :) Проблема в этом - news.*,news_content.* - там действительно два одинаковых столбца. решается просто - хотябы для одной таблицы прописываеш столбцы, исключая дублируюущиеся. вообще пользование конструкции SELECT * FROM не есть хороший тон.
 

igortik

Новичок
john.brown
согласен... согласен... подумаю на досуге... правда, я не часто так делаю.

кстати, решение само пришло... я вспомнил для чего я затеял все это... чтобы не делать 2 раза один и тот же запрос...

т.е. сейчас поставил:
$this->total_rows = mysql_num_rows($db->query($this->query)); // всего записей

т.е. считаем сколько всего записей...
потом дорабатывается строка запроса:
$query .= " LIMIT $this->start_from, $this->row_limit";

и запрос выполняется повторно..

не кидайте в меня камни...

-~{}~ 23.07.10 21:07:

это мне однозначно не по душе... вытягивать все записи...... епт, чтобы потом их ф-ией считать... \

пойду отдышусь ...
 

john.brown

просто кулибин
igortik
так по любому ты делаеш два раза один и тот же запрос :) но, имхо, средствами sql считать правилнее.
 

igortik

Новичок
john.brown
вот я о том же.. в моем случае я не просто считаю средствами php, так еще и тяну селектом все данные полей :(

-~{}~ 23.07.10 21:18:

prolis
подсказал дело, действительно ...
но мускул орет о дублированных полях, хотя, такого не возникает в том случае, когда запрос не вкладывается в select count(*) from ( ... )
 

igortik

Новичок
iceman
ну я тоже так и подумал, что стоит выбирать данные без дублирования полей и метод

PHP:
$query_count='select count(*) from ('.$this->query.')';
целиком подойдет.

-~{}~ 24.07.10 14:01:

вдогонку доработаю класс page_limiter таким образом, чтобы он мог получать и отдельный упрощенный $query_count, в принципе, как и надо было изначально делать ...
 

Mols

Новичок
Ну хз.
Учитывая то, что это паджинатор.
То наверное можно предположить, что запрос будет всегда
СЕЛЕКТ что-то ФРОМ источник+условия.
Ну и передавал бы в метод 2 параметра
ЧудоМетод("что-то", "источник+условия")
А там уже строил бы либо
СЕЛЕКТ что-то ФРОМ источник+условия.
либо
СЕЛЕКТ count(*) ФРОМ источник+условия.

З.Ы.
ИМХО Вы "хотите странное"
 
Сверху