首页 > 解决方案 > 如何使用查询生成器根据实际字段中的表进行条件 mysql 左连接

问题描述

在设置产品时,我可以选择将其可用性限制在客户的国家、地区和城市。基于此,我只向系统中符合此条件的相关客户展示产品。

在某些情况下,我只想将产品设置为国家/地区而忽略城市,我想知道如何最好地编写此查询。

在我看来,我有两个选择。

  1. 如果产品与所有城市和地区相关,只需将它们全部包含(大量数据)。
  2. 如果不需要城市/地区,只需忽略限制它们的语句。

产品:

+---------------------+------------------+------+-----+---------+----------------+
| Field               | Type             | Null | Key | Default | Extra          |
+---------------------+------------------+------+-----+---------+----------------+
| id                  | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| uuid                | binary(16)       | NO   | UNI | NULL    |                |
+---------------------+------------------+------+-----+---------+----------------+

多对多连接到位置

+------------------+------------------+------+-----+---------+-------+
| Field            | Type             | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+-------+
| product_id          | int(10) unsigned | NO   | PRI | NULL    |       |
| meta_location_id | int(11)          | NO   | PRI | NULL    |       |
+------------------+------------------+------+-----+---------+-------+

地点

+-------------+---------------+------+-----+---------+----------------+
| Field       | Type          | Null | Key | Default | Extra          |
+-------------+---------------+------+-----+---------+----------------+
| id          | int(11)       | NO   | PRI | NULL    | auto_increment |
| iso         | varchar(50)   | YES  |     | NULL    |                |
+-------------+---------------+------+-----+---------+----------------+

查询生成器代码

$qb = $this->repository->createQueryBuilder('product');
$qb->orderBy('product.id', 'ASC');

//If we are limiting by country
if (isset($options['country']) and null !== $options['country']) {
    $qb->andWhere('product.country = :country')
        ->setParameter('country', $options['country']);
}

地区/城市:

区域选项是客户的当前区域,无论如何都会发送,我无法控制它。由于我在产品表中搜索,我需要检查产品区域是否存在。如果是这样,那么我必须将其限制在现有区域,否则忽略它。

CURRENT QUERY:使用此查询,如果区域不匹配,则不会列出产品。我想将其更改为仅适用于产品表中存在数据的情况。

   if (isset($options['region']) and null !== $options['region']) {
        $qb->leftJoin('product.regions', 'region');
        ->andWhere(($qb->expr()->in('region', [$options['region']])));
    }

我猜我需要一些类似的东西

    $qb->add('select', 'CASE WHEN region.id IS NOT NULL then do some query...

任何想法,将不胜感激!

标签: mysqldoctrine-ormquery-builder

解决方案


这就是我解决这个问题的方法。

而不是做一些复杂的事情,比如试图弄清楚一个连接是否包含数据。我只是在我们的元位置表中创建了一个虚拟行。

我们的连接现在看起来像这样:

  if (isset($options['region']) and null !== $options['region']) {
        $qb->leftJoin('product.regions', 'region');
        ->andWhere(($qb->expr()->in('region', [12345, $options['region']])));
  }

其中 12345 是虚拟行的 ID。

设置产品时,在表单下拉菜单中,我有一个名为“任何”的项目,这意味着客户居住在哪个地区并不重要,就像任何地区一样。

因此,如果选择了任何连接,则现在连接将有效,否则,如果该区域与实际区域匹配,则它也可以工作。

好吧,我们有它,通常最简单的解决方案是最好的!


推荐阅读