有人可以建议一种使用带有多个“where”子句的 Doctrine (QueryBuilder) 进行此查询的方法吗?

Posted

技术标签:

【中文标题】有人可以建议一种使用带有多个“where”子句的 Doctrine (QueryBuilder) 进行此查询的方法吗?【英文标题】:Can someone suggest a way to do this query using Doctrine (QueryBuilder) with multiple "where" clause? 【发布时间】:2020-12-10 21:46:53 【问题描述】:

我是 QueryBuilder 的新手,我正在尝试执行一个 POST 请求(使用 JSON)来检索我的数据库中的一些信息。

我使用数组是因为每个属性都可以有多个值。这是我当前发送的 JSON:


    "name":["Martin"],
    "state":["Ohio", "Texas"],
    "job":["Photographer", "Reporter"]

这是我的数据库:

ID  |   NAME        |   FIRST_NAME  |   STATE       |   JOB             |   SPEAK_FRENCH
1   |   Martin      |   John        |   Ohio        |   Photographer    |   1
2   |   Martin      |   Max         |   Ohio        |   Reporter        |   1
3   |   Martin      |   Sophie      |   Texas       |   Model           |   1
4   |   Alexander   |   David       |   Kansas      |   Author          |   0
5   |   Archie      |   Kira        |   Maine       |   Photographer    |   1
6   |   Lushen      |   Albert      |   Nevada      |   Pilot, Model    |   1
7   |   Wilkins     |   Minnie      |   Utah        |   Tailor          |   0
8   |   Martin      |   Thomas      |   Texas       |   Reporter        |   1
9   |   Patino      |   Stephen     |   Virginia    |   Pilot, Reporter |   1
10  |   Ting        |   Maria       |   Nevada      |   Dentist         |   0
11  |   Brown       |   Barbara     |   Virginia    |   Reporter        |   1
12  |   Martin      |   William     |   Texas       |   Photographer    |   1
13  |   Zachary     |   Thomas      |   Virginia    |   Telephonist     |   1

我想要的请求:

SELECT * FROM 'application'
WHERE SPEAK_FRENCH = 1
AND NAME = "Martin"
AND STATE = "Ohio"
AND JOB LIKE "%Photographer%"
OR SPEAK_FRENCH = 1
AND NAME = "Martin"
AND STATE = "Ohio"
AND JOB LIKE "%Reporter%"
OR SPEAK_FRENCH = 1
AND NAME = "Martin"
AND STATE = "Texas"
AND JOB LIKE "%Photographer%"
OR SPEAK_FRENCH = 1
AND NAME = "Martin"
AND STATE = "Texas"
AND JOB LIKE "%Reporter%"

而我目前在 Symfony 中所做的事情并没有按照我想要的方式工作:

$repository = $this->getDoctrine()->getRepository(Application::class);
$query = $repository->createQueryBuilder('request');
$temp_name = 0;
$temp_state = 0;
$temp_job = 0;
foreach ($app->getName() as $name) 
    $temp_name = $temp_name + 1;

    $query = $query->orWhere('request.speakFrench = 1')
        ->andWhere('request.name LIKE :JSONname' . strval($temp_name))
        ->setParameter('JSONname' . strval($temp_name), $name);

    foreach ($app->getState() as $state) 
        $temp_state = $temp_state + 1;

        $query = $query->andWhere('request.state LIKE :JSONstate' . strval($temp_state))
            ->setParameter('JSONstate' . strval($temp_state), $state);

        foreach ($app->getJob() as $job) 
        $temp_job = $temp_job + 1;

        $query = $query->andWhere('request.job LIKE :JSONjob' . strval($temp_job))
            ->setParameter('JSONjob' . strval($temp_job), '%' . $job . '%');
        
    

我的目标是得到这个结果:

ID  |   NAME        |   FIRST_NAME  |   STATE       |   JOB             |   SPEAK_FRENCH
1   |   Martin      |   John        |   Ohio        |   Photographer    |   1
2   |   Martin      |   Max         |   Ohio        |   Reporter        |   1
8   |   Martin      |   Thomas      |   Texas       |   Reporter        |   1
12  |   Martin      |   William     |   Texas       |   Photographer    |   1

我的代码运行不正常,它没有发送任何错误,只返回ID : 8

我正在寻找一种方法来执行仅返回 ID : 1, 2, 8 and 12 的查询。

非常感谢您未来的回答。

P.S : 我正在运行 Symfony 4.3.11。

【问题讨论】:

@Strawberry 我想要一个功能齐全的查询,它可以真正按照我想要的方式工作(返回 id 1、2、8 和 12)。我在 php 中发布的代码只返回“最后一个”查询,就像我发送了这个 json 一样: "name":["Martin"], "state":["Texas"], "job":["Reporter"] 如果您需要速度,那么从您的 json 字段构建原始 sql 字符串将是答案。如果您想要简单,我有时会做类似->where('request.name LIKE "%theName%"')->andWhere('request.job = "job1" OR request.job = "job2'') 之类的事情。你的情况会有所不同,但也许我给了你一些想法。 我可能在这里遗漏了一些微妙的点,但我不明白为什么 IN 运算符不适合你: WHERE name IN (:names) A​​ND state IN (:states) 等 DQL 是很好,因为它可以处理 IN 运算符的数组参数。 @MartinM。我想我肯定会使用类似的东西,是的,谢谢你的帮助。 是的,我很少需要使用IN 所以我忘记了,但Cerad 是正确的。 【参考方案1】:

以 Doctrine 为例,您可以这样做:

    $queryBuilder = $this->createQueryBuilder('request');
    $queryBuilder
        ->andWhere($queryBuilder->expr()->andX(
            $queryBuilder->expr()->eq('user.speakFrench', ':speakFrench'),
            $queryBuilder->expr()->like('request.name', ':name'),
            $queryBuilder->expr()->in('request.state', ':states'),
            $queryBuilder->expr()->in('request.job', ':jobs'),
        ))
        ->setParameter('speakFrench', true)
        ->setParameter('name', 'Martin')
        ->setParameter('states', ['Ohio', 'Texas'])
        ->setParameter('jobs', ['Photographer', 'Reporter'])
        ->getQuery()
        ->getResult();

这应该是一个好的开始。

继续:

Doctrine 用法的许多示例:Hot examples 查看Doctrine\ORM\Query\Expr 类,有很多有用的功能。 Doctrine Expr GitHub 查看提供许多示例的文档:Doctrine Query Builder

【讨论】:

谢谢,一定会帮助我的!【参考方案2】:

以下似乎是符合您要求的有效查询:

SELECT * 
  FROM application
 WHERE SPEAK_FRENCH = 1
    AND NAME = "Martin"
    AND STATE = IN("Ohio","Texas")
    AND (JOB LIKE "%Photographer%" OR JOB LIKE "%Reporter%");

另外,请参阅Is storing a delimited list in a database column really that bad?

【讨论】:

对我有帮助,谢谢。如果我有多个名字,这是否同样有效?你对如何使用 Doctrine QueryBuilder 有任何想法吗? 规范化你的架构。然后,您可以对所有条件使用 IN()(和索引)。

以上是关于有人可以建议一种使用带有多个“where”子句的 Doctrine (QueryBuilder) 进行此查询的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

带有插入语句的 Where 子句

具有多个带有 AND 类型逻辑连接的 where IN 子句的配置单元查询

Haskell:具有多个***绑定的“where”子句?

Oracle SQL Where 子句查找超过 30 天的日期记录

带有 WHERE 子句的 SQL COUNT

where子句中的多个字符匹配