Doctrine2 DBAL Exists запрос
Я хотел бы попросить вас о помощи с Doctrine2 DBAL
запрос построен с QueryBuilder
, Я привык к ORM, но я думаю, что это избыточный запрос для такого запроса, который вызывается в слушателе.
Мне нужен запрос с SELECT EXISTS
и я не знаю, как я могу построить это с помощью DBAL QueryBuilder
,
У меня уже есть подзапрос:
$subQuery = $connection->createQueryBuilder();
$subQuery
->select('o.id')
->from('order', 'o')
->leftJoin('o', 'payment', 'p')
->where($subQuery->expr()->isNull('p.id'))
;
Я в основном хочу проверить, есть ли какие-либо неоплаченные заказы. Теперь я понятия не имею, как построить SELECT EXISTS
запрос? Может кто-то указать мне верное направление? Я думал о чем-то вроде этого:
$qb->select('EXISTS(?)')->setParameter($subQuery->getDQL())
Это будет правильное решение?
@РЕДАКТИРОВАТЬ
Спустя некоторое время я решил использовать ORM. К сожалению, это не сработало, я получаю сообщение об ошибке:
line 0, col 7: Error: Expected known function, got 'EXISTS'
DQL это:SELECT EXISTS(<subquery here>)
Это немного странно, учитывая, что он был собран с QueryBuilder:
/* @var $qb QueryBuilder */
$qb = $this->em->createQueryBuilder();
$qb
->select($qb->expr()->exists($subQuery->getDQL()));
0 ответов
С опозданием на несколько лет, но вам нужно указать EXISTS
подзапрос SQL в SELECT
или WHERE
часть выражения QueryBuilder, а не использование параметра.
Кроме того, поскольку order
является зарезервированным словом в MySQL, вам нужно будет использовать кавычки идентификатора `
(обратная галочка), чтобы избежать имени таблицы.
При использовании ORM; вы должны указатьFROM
утверждение, которое ссылается на сущность, поэтому вам придется изменить свой подход.
$expr = $connection->getExpressionBuilder();
$qbSub = $connection->createQueryBuilder()
->select(['1'])
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $exor->eq('p.order_id', 'o.id'))
->where($expr->isNull('p.id'));
/**
* @return string "1" if a record exists, "0" otherwise
*/
$connection->createQueryBuilder()
->select('EXISTS(' . $qbSub->getSQL() . ')')
->execute()
->fetchColumn();
Примечание. Если у вас есть какие-либо параметры, значения для заполнителей должны быть связаны с использованием
QueryBuilder::setParameter()
в запросе верхнего уровня, а не в подзапросах.
$qb
->setParameter('name', $value)
->execute();
Результирующий SQL
SELECT EXISTS(
SELECT 1
FROM `order` AS o
LEFT JOIN `payment` AS p
ON p.order_id = o.id
WHERE p.id IS NULL
);
Однако я предлагаю изменить ваш запрос с соединения исключения на соединение включения с NOT EXISTS
. Это отфильтрует оплаченные заказы из вашего набора результатов. Вместо того, чтобы пытаться присоединять каждый заказ к каждому платежу и получать возвращаемые платежиnull
. Значительное повышение производительности запроса.
Пример db-fiddle
SELECT EXISTS (
SELECT 1
FROM `order` AS o2
WHERE NOT EXISTS(
SELECT NULL
FROM `order` AS o
INNER JOIN `payment` AS p
ON p.order_id = o.id
WHERE o2.id = o.id
)
)