如何使用查询构建器在实际字段中基于 table 进行条件 mysql 左连接

How to do a conditional mysql left join based on table in the actual fields using query builder

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

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

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

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

产品:

+---------------------+------------------+------+-----+---------+----------------+
| 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']);
}

REGIONS/CITIES:

区域选项是客户当前所在的区域,这个是不管发送的,我无法控制。由于我正在搜索产品 table,因此我需要检查产品区域是否存在。如果是这样,那么我必须将其限制在现有区域中,否则将忽略它。

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

   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...

如有任何想法,我们将不胜感激!

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

而不是做一些复杂的事情,比如试图弄清楚连接是否包含数据。我只是在我们的元位置 table.

中创建了一个虚拟行

我们的加入现在看起来像这样:

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

其中 12345 是虚拟行的 ID。

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

所以现在,如果选择了任何连接,连接将有效,否则,如果该区域与实际区域匹配,那么它也有效。

好吧,我们知道了,通常最简单的解决方案是最好的!