Материал для экспертов.
Вообще с этой задачей бился не один год, и вот только сегодня победил…
Задача: средствами xPDO в запрос добавить подзапрос, то есть еще один select. Пример такого запроса:
Вообще, если у кого-то есть свои варианты решения данной задачи, напишите в комментариях, было бы интересно глянуть.
Итак, простого решения я не нашел. Вариант типа $q->leftJoin("(select * from modx_users)", «t1», «modResource.creteadby = t1.id»); не канает, так как xPDOQuery::leftJoin() ожидает первым параметром имя xPDO-класса, получив который будет пытаться определить имя таблицы методом xPDO::getTableName(). В результате мы получим ошибку:
Вот мой вариант решения этой задачи:
Можно этот же запрос расширить xPDO-подзапросом:
На выходе получаем SQL-запрос:
Такой метод формирования запроса хорош тем, что имеющийся объект xPDOQuery $q можно использовать и для подсчета количества найденных строк $modx->getCount('modResource', $q), и для установки лимитов $q->limit($limit), и для сортировки $q->sortby(«modResource.id», «ASC»); и т.д. и т.п.
Так же можно и в объекты сразу набивать $modx->getCollection(«modResource», $q) или $modx->getIterator(«modResource», $q). В общем, xPDO API можно использовать в полной мере.
Так же в процессе поиска данного решения был освоен и иной промежуточный вариант:
Получаемый запрос:
Но, во-первых, это эквивалент inner join (то есть left join уже не получается, если нужен), а во-вторых, давно уже такой вариант запроса не считается стандартом, JOIN-ы предпочтительней.
А что с производительностью, ведь подзапросы нагружают базу?
Может быть я чего-то не понимаю, но почему бы не сделать leftJoin modResource и modUser, или это просто пример не удачный?
Пример не неудачный, он просто простой. Вот пример посложнее:
SQL:
Здесь выборка несколько килотоваров с группировкой по полю (тут товары с вариациями товаров). И вот когда у всех товаров были заполнено это дополнительное поле, участвующее в группировке, тогда да, обычным запросом обходился. А теперь появились товары, у которых это поле не было заполнено. Пришлось переписывать запрос, так как если я сейчас сделаю группировку по этому незаполненному полю, у меня будут сотни товаров в одной карточке, а если я исключу такие товары, то они у меня просто не попадут в выборку.
На счет производительности: не самый шустрый вариант, конечно, но более хитрый вариант без подзапроса с дополнительными условиями вообще мускул ложили. В целом, джоинить такой подзапрос не особо нагруженно, так как там получается связь один-к-одному. Здесь выборка из нескольких килотоваров на холодную 2 секунды занимает. Запросы кешируются, так что в целом сайт будет работать нормально.