首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Doctrine2数据库存在查询

Doctrine2数据库存在查询
EN

Stack Overflow用户
提问于 2016-12-14 10:52:27
回答 1查看 2.4K关注 0票数 2

我想请您帮助使用Doctrine2 DBAL构建的QueryBuilder查询。我已经习惯了ORM,但我认为这对在侦听器中调用的这样的查询来说是过分的。

我需要一个SELECT EXISTS查询,我不知道如何使用DBAL QueryBuilder来构建它。

我已经创建了一个子查询:

代码语言:javascript
复制
$subQuery = $connection->createQueryBuilder();
$subQuery
    ->select('o.id')
    ->from('order', 'o')
    ->leftJoin('o', 'payment', 'p')
    ->where($subQuery->expr()->isNull('p.id'))
;

我基本上是想检查一下是否有任何未付的订单。我现在不知道如何构建SELECT EXISTS查询?谁能给我指明正确的方向?我在想这样的事情:

代码语言:javascript
复制
$qb->select('EXISTS(?)')->setParameter($subQuery->getDQL())

这是正确的解决办法吗?

@编辑

经过一段时间的思考,我决定用ORM代替。不幸的是,这也不起作用,我收到一个错误:

line 0, col 7: Error: Expected known function, got 'EXISTS'

DQL是:SELECT EXISTS(<subquery here>)

考虑到它是用QueryBuilder构建的,这有点奇怪:

代码语言:javascript
复制
/* @var $qb QueryBuilder */
$qb = $this->em->createQueryBuilder();
$qb
        ->select($qb->expr()->exists($subQuery->getDQL()));
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-19 04:46:41

几年后,您需要在EXISTSSELECTWHERE语句部分中指定QueryBuilder子查询SQL,而不是使用参数。

此外,由于order是MySQL中的保留字,因此需要使用标识符引号` (回勾)来转义表名。

使用ORM时,必须指定引用实体的FROM语句,因此需要更改方法。

代码语言:javascript
复制
$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

代码语言:javascript
复制
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()绑定,而不是在子查询中绑定。

代码语言:javascript
复制
$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的付款。极大地提高了查询的性能。

示例 大小提琴

代码语言:javascript
复制
SELECT EXISTS (
    SELECT 1
    FROM `order` AS o
    WHERE NOT EXISTS(
        SELECT NULL
        FROM `payment` AS p
        WHERE p.order_id = o.id
    )
)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41140768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档