如何使用查询构建器在实际字段中基于 table 进行条件 mysql 左连接
How to do a conditional mysql left join based on table in the actual fields using query builder
在设置产品时,我可以选择将其可用性限制在客户的国家、地区和城市。基于此,我只向系统中符合此条件的相关客户展示产品。
在某些情况下,我只想将产品设置为 country/region 并忽略城市,我想知道如何最好地编写此查询。
在我看来,我有两个选择。
- 如果一个产品与所有城市和地区相关,只需将它们全部包括在内(大量数据)。
- 如果不需要 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" 的项目,这意味着客户居住在哪个地区并不重要,因为任何地区都会这样做。
所以现在,如果选择了任何连接,连接将有效,否则,如果该区域与实际区域匹配,那么它也有效。
好吧,我们知道了,通常最简单的解决方案是最好的!
在设置产品时,我可以选择将其可用性限制在客户的国家、地区和城市。基于此,我只向系统中符合此条件的相关客户展示产品。
在某些情况下,我只想将产品设置为 country/region 并忽略城市,我想知道如何最好地编写此查询。
在我看来,我有两个选择。
- 如果一个产品与所有城市和地区相关,只需将它们全部包括在内(大量数据)。
- 如果不需要 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" 的项目,这意味着客户居住在哪个地区并不重要,因为任何地区都会这样做。
所以现在,如果选择了任何连接,连接将有效,否则,如果该区域与实际区域匹配,那么它也有效。
好吧,我们知道了,通常最简单的解决方案是最好的!