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
    )
)
Другие вопросы по тегам