晚了几年,但你需要具体说明你的EXISTS
子查询 SQL 内SELECT
or WHERE
QueryBuilder 的语句部分,而不是使用参数。
另外因为order
是 MySQL 中的保留字,您需要使用标识符引号`
(反勾)转义表名。
使用 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
);
注意:如果有任何参数,则必须使用绑定占位符的值QueryBuilder::setParameter()
在顶层
查询,而不是子查询。
$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
。这样做将从结果集中过滤掉已付款的订单。而不是尝试加入每笔付款的每个订单并检索返回的付款null
。极大地提高了查询的性能。
Example 数据库小提琴 https://www.db-fiddle.com/f/9pMJYXijCt2nVg62oX54xq/0
SELECT EXISTS (
SELECT 1
FROM `order` AS o
WHERE NOT EXISTS(
SELECT NULL
FROM `payment` AS p
WHERE p.order_id = o.id
)
)