Doctrine как получить расхождение двух запросов?
Здравствуйте. Суть вопроса.
Есть два селекта, надо получить их расхождение.
Делаю так:
SELECT * FROM tbl1 EXCEPT SELECT * FROM tbl2
На чистом SQL все работает, все хорошо. А теперь то же самое на DQL.
А доктрина так не умеет. Вариант какой... делаем так:
$query1 = $this->em->createQueryBuilder() ->select('c') ->form(MyClass::class, 'c') ->getQuery() ->getDQL(); $query2 = this->em->createQueryBuilder() ->select('c') ->form(OtherMyClass::class, 'c') ->getQuery() ->getDQL(); $dql = $query1 . ' EXCEPT ' . $query2; $this->em ->createQuery($dql) ->getResult(); |
$query1 = $this->em->createQueryBuilder() ->select('c') ->form(MyClass::class, 'c') ->getQuery() ->getDQL(); $query2 = this->em->createQueryBuilder() ->select('c') ->form(OtherMyClass::class, 'c') ->getQuery() ->getDQL(); $dql = $query1 . ' EXCEPT ' . $query2; $this->em ->createQuery($dql) ->getResult();
Да не тут то было. Доктрина не знает слова EXCEPT. Но мы ж не пальцем деланные, есть возможность регистрировать пользовательские языковые конструкции, типа DATEDIFF и все такое.
Делаем класс ExceptFunction extends FunctionNode, прописываем его в дотриновском конфиге, если запросить $this->em->getConfiguration() то наш класс там видно, все хорошо. Но эта гадость все равно не разбирает запрос. Такое ощущение что мой класс ExceptFunction не вызывается вообще при разборе DQL внутренностями доктрины. Видимо я что то делаю не так. А что не так понять не могу. Подскажите люди добрые, кто пользовался этой штукой, в чем моя проблема?
Дополнительно:
Ответы:
Делаю так:
SELECT * FROM tbl1 EXCEPT SELECT * FROM tbl2
Структуры таблиц совпадают?
Тогда
SELECT t1.* FROM tbl1 LEFT JOIN tbl2 ON tbl1.primary_key = tbl2.primary_key WHERE t2.primary_key IS NULL |
SELECT t1.* FROM tbl1 LEFT JOIN tbl2 ON tbl1.primary_key = tbl2.primary_key WHERE t2.primary_key IS NULL
Это должно без проблем отображаться на синтаксис фреймворка.
- Не совпадают. На самом деле там сложные запросы с несколькими join, агрегатными функциями, вот этим вот всем. Результат выдачи совпадает. Но не всегда. Вот и надо отловить это "не всегда". Так что обычным join эту проблему не решить. Да и вообще на будущее научиться бы как правильно в доктрину свои языковые конструкции добавлять
- Doctrine ORM не реализует в полной мере возможности нативного синтаксиса, что мешает выполнить native запрос а entity если нужны через гидратор сделать ?
- https://github.com/doctrine/orm/blob/2.10.x/lib/Do...
- Сергей Доний,
что мешает выполнить native запрос
- чувство прекрасного. Весь код в единой стилистике с PSRами, вот этим вот всем и тут посреди кода фаршмак в виде обычного SQl - согласитесь, это некрасиво. Сущности получать не надо, мне достаточно инфы что ответ не пустой, т.е. расхождения в ответах есть. Пока я так и сделал, нативным SQL. Но гложет червь сомнения - что такая задача может решаться более изящными способами. Вариант сделать первый запрос, потом второй и сделать array_diff между ними - не предлагать :)
- Dark_Dante,
Не совпадают.
Ну раз не совпадают, то и EXCEPT не заработает - даже там, где он реализован.
Впрочем, на показанный мной шаблон это никак не влияет. Всё равно связывание надо вести по уникальному идентифицирующему выражению.
- Akina, Суть в чем. Приезжают товары в контейнерах (не суть важно, важно что большой объем). Есть таблица где сведены id контейнера, id товара, количество единиц товара в контейнере. Уезжают товары в мелкой фасовке - пакеты. Есть таблица где тоже самое: id пакета, id товара, количество единиц товара в пакете. Количество контейнеров с одинаковыми товарами за одну доставку может быть любым. И количество пакетов с разными товарами тоже может быть любым. Я этим запросом делаю что... группирую все контейнеры данной доставки по id товара и делаю SUM(количество). И тоже самое с пакетами. И смотрю расхождение первого со вторым - ничего не прое... потерялось ли. Если расхождение есть - единица товара либо пролюбилась, либо добавилась неучтенная в пакете. К тому же в пакете могут быть дополнительные товары, которых не было в контейнерах. Твой вариант отработает до момента пока не появятся в пакетах эти дополнительные товары, разве нет?
- Dark_Dante, нету в MySQL FULL JOIN, нету! только LEFT/RIGHT.
Хочешь дополнительные товары увидеть - используй тот же шаблон, но реверсно.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для того чтобы получить расхождение двух запросов в Doctrine, можно воспользоваться методом QueryBuilder::getQuery() для каждого запроса и сравнить полученные результаты.
Прежде всего необходимо создать два объекта QueryBuilder, в которых будут содержаться два различных запроса к базе данных. Затем для каждого из них вызывается метод getQuery(), который возвращает объект Query, содержащий результирующий SQL-запрос.
После этого необходимо выполнить оба запроса и получить результаты. Результаты запросов могут быть представлены в виде массивов или объектов, в зависимости от того, что возвращает запрос.
Далее необходимо сравнить результаты двух запросов и выявить различия между ними. Для этого можно использовать различные методы сравнения массивов или объектов, например, с помощью функции array_diff() для сравнения массивов или метода equals() для сравнения объектов.
Если результаты запросов отличаются, то можно определить причину этого расхождения. Возможно, в запросах содержатся различные условия, сортировки или выборки данных, которые приводят к различиям в результирующих наборах данных.
Таким образом, для получения расхождения двух запросов в Doctrine необходимо выполнить оба запроса, получить результаты и сравнить их, чтобы определить причину отличий.