Doctrine DQL: как выбрать объекты из двух таблиц с разными условиями?

Есть два класса сущностей, хочу выбрать объекты из их таблиц одним запросом:
SELECT d, e 
        FROM OrganizerBundle:DailyTask d, OrganizerBundle:Event e
        WHERE d.weekday = 'all' OR DATE_FORMAT(e.date,'%Y-%m-%d') = :date


Как видно, я хочу выбрать DailyTask, у которых weekday = 'all' и Event, у которых date = :date . Проблема - условие WHERE работает только для первой таблицы, а из второй выбираются все элементы.

Как прописать так, чтобы условия были отдельными для двух таблиц? UNION не предлагать - Doctrine не поддерживает.

Вот запрос SQL, который генерируется в результате:
ELECT d0_.weekday AS weekday_0, d0_.time AS time_1, d0_.length AS length_2, d0_.id AS id_3, d0_.name AS name_4, d0_.description AS description_5, e1_.date AS date_6, e1_.length AS length_7, e1_.id AS id_8, e1_.name AS name_9, e1_.description AS description_10 FROM daily d0_, events e1_ WHERE (d0_.weekday = 'all') OR (DATE_FORMAT(e1_.date,'%Y-%m-%d') = '2017-07-08')


Что-то я не вспомню, как и в MySQL без использования UNION такой трюк провернуть.
  • Вопрос задан
  • 1972 просмотра
Решения вопроса 1
@miksir
IT
Если вам нужен результат - то два запроса. Если вам гланды через зад, то docs.doctrine-project.org/en/latest/reference/nati...
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Melkij
@Melkij
PostgreSQL DBA
Проблема - условие WHERE работает только для первой таблицы, а из второй выбираются все элементы.

Вывод неверен. Выполняются оба условия, гарантированным seqscan'ом по events, если повезёт то index scan'ом по weekday. А в результате, как в запросе и написано - выборки перемножаются между собой в cross join.

Если таблицы не связаны и нужен плоский список - то здесь нужен именно union all. Глупая доктрина его не умеет. Возможные методы извращения без union глупая доктрина не умеет тем более.
Значит или обучать доктрину делать union all (вероятно, нетривиально)
или делать два запроса (всё равно у вас сейчас seqscan, значит производительность вам не нужна и explain никто не смотрел)
или делать вьюшку в базе с union all и ходить к ней вместо таблиц (и проверить, умеет ли планировщик каждой из поддерживаемых баз вообще прокидывать условия внешнего запроса во вьюшки с union all)
или использовать native query с нормальным SQL

PS: да, я с доктриной работал и именно поэтому её сильно не люблю за ограниченность синтаксиса, при том всё равно с нещадно текущими абстракциями и необходимостью знать и учитывать чем именно каждая поддерживаемая база отличается от других. И нафига эта доктрина тогда вообще жрёт столько cpu и памяти?
Ответ написан
@djay
Как прописать так, чтобы условия были отдельными для двух таблиц? UNION не предлагать - Doctrine не поддерживает.


И что теперь если поддерживает? Доктрина - не решает данную задачу, посколько является лишь обычным построителем запросов. Задачу решает здесь SQL. В таких cлучаях можно использовать RAW query отбросив перфекционизм:

$connection = $em->getConnection();
$query = $connection->prepare("SELECT field1, field2 FROM table1 
                                UNION
                                SELECT field3, field4 FROM table2 
                                UNION 
                                SELECT field5, field6 FROM table3
                                ");
$query->execute();
$result = $query->fetchAll();
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы