Doctrine2 DBAL Exists 查询
Doctrine2 DBAL Exists query
我想请求您帮助使用 QueryBuilder
构建的 Doctrine2 DBAL
查询。我已经习惯了 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()));
晚了几年,但您需要在 QueryBuilder 的 SELECT
或 WHERE
语句部分指定 EXISTS
子查询 SQL,而不是使用一个参数。
此外,由于 order
是 MySQL 中的保留字,您需要使用标识符引号 `
(反引号)来转义 table 名称。
使用ORM时;您必须指定引用实体的 FROM
语句,因此您需要更改方法。
$connection = $this->em->getConnection();
$expr = $connection->getExpressionBuilder();
$qbSub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->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();
结果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
);
Note: If you have any parameters, the values for the placeholders must be bound using QueryBuilder::setParameter()
on the top-level
query, not the sub-queries.
$qbsub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->andX(
$expr->eq('p.order_id', 'o.id'),
$expr->eq('p.name', ':name') // subquery placeholder
))
->where($expr->isNull('p.id'));
$connection->createQueryBuilder()
->select('EXISTS(' . $qbSub->getSQL() . ')')
->setParameter('name', $value) // subquery placeholder param value
->execute()
->fetchColumn();
但是,我建议将您的查询从排除连接更改为使用 NOT EXISTS
的包含连接。这样做将从您的结果集中过滤已支付的订单。而不是尝试在每次付款时加入每个订单并检索 return null
的付款。显着提高查询性能。
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
)
)
我想请求您帮助使用 QueryBuilder
构建的 Doctrine2 DBAL
查询。我已经习惯了 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()));
晚了几年,但您需要在 QueryBuilder 的 SELECT
或 WHERE
语句部分指定 EXISTS
子查询 SQL,而不是使用一个参数。
此外,由于 order
是 MySQL 中的保留字,您需要使用标识符引号 `
(反引号)来转义 table 名称。
使用ORM时;您必须指定引用实体的 FROM
语句,因此您需要更改方法。
$connection = $this->em->getConnection();
$expr = $connection->getExpressionBuilder();
$qbSub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->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();
结果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
);
Note: If you have any parameters, the values for the placeholders must be bound using
QueryBuilder::setParameter()
on the top-level query, not the sub-queries.
$qbsub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->andX(
$expr->eq('p.order_id', 'o.id'),
$expr->eq('p.name', ':name') // subquery placeholder
))
->where($expr->isNull('p.id'));
$connection->createQueryBuilder()
->select('EXISTS(' . $qbSub->getSQL() . ')')
->setParameter('name', $value) // subquery placeholder param value
->execute()
->fetchColumn();
但是,我建议将您的查询从排除连接更改为使用 NOT EXISTS
的包含连接。这样做将从您的结果集中过滤已支付的订单。而不是尝试在每次付款时加入每个订单并检索 return null
的付款。显着提高查询性能。
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
)
)