过滤 2 个表中的数据并从两个表中获取结果

问题描述 投票:0回答:1

如何过滤 2 个表中的数据集,其中第二个表有更多结果 1:n。

在第一个表中,我可以使用 orWhere 并且获得正确的数据,但我的另一个表包含多个结果,如果我使用包含或匹配,我只能从第二个表获取数据。

所以,我想过滤两个表并获取匹配的数据。

这是我的询问:

第一个查询来过滤第一个表

$query
      ->where([
        'OR' => [
          'Orders.id' => $freeText,
          'Orders.postal' => $freeText,
          'Orders.address LIKE' => '%' . $freeText . '%',
          'Orders.city LIKE' => '%' . $freeText . '%',
          'Users.first_name' => $freeText,
          'Users.last_name' => $freeText,
          'ProjectAddresses.cost_centre' => $freeText,
          'CONCAT(first_name, last_name) LIKE' => '%' . str_replace(' ', '', $freeText) . '%',
          'CONCAT(first_name, last_name) LIKE' => '%' . $freeText . '%',
          'Users.first_name IN ' => $splittedKeywords,
          'Users.last_name IN ' => $splittedKeywords,
        ]
      ]);

第二个查询 - 尝试从第二个表中过滤数据(但仍然需要第一个表中的匹配数据)

$query->contain('Items', function ($q) use ($freeText) {
    return $q->where(['vessel_id' => $freeText]);
});

所以问题是,如果我使用第二个查询,他会自动仅从第二个表中获取数据,而我的目标是获取所有过滤后的数据(来自第一个和第二个表)。

我有 20 多个数据集,例如:

(int) 0 => [
        'id' => (int) 1,
        'uuid' => '5f34ecda-6bc6-46ed-b5cc-b2227029aed8',
        'user_id' => (int) 319,
        'status' => (int) 30,
        'order_price' => (float) 341.04,
        'address_id' => (int) 379,
        'address' => 'XYZ',
        'building_number' => '171',
        'postal' => '111',
        'city' => 'XYZ',
        'country' => 'AT',
        'project_address' => [
            'id' => (int) 379,
            'type' => 'project',
            'group_id' => (int) 3,
            'default' => false,
            'corresponding_invoice_address' => null,
            'short_name' => 'XYT',
            'comment' => '',
        ],
        'user' => [
            'id' => (int) 319,
            'uuid' => '675216eb-7110-44d2-82a7-f7f020e934a6',
            'title' => 'Herr',
            'first_name' => 'Test',
            'last_name' => 'Test',
        ],
        'item_groups' => [],
        'items' => [
            (int) 0 => [
                'id' => (int) 26,
                'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
                'item_group_id' => null,
                'type' => (int) 2,
                'status' => (int) 30,
                'vessel_id' => (int) 40001,
                'features' => [],
            ],
            (int) 1 => [
                'id' => (int) 28,
                'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
                'item_group_id' => null,
                'type' => (int) 2,
                'status' => (int) 30,
                'vessel_id' => (int) 40003,
                'features' => [],
            ],
            (int) 1 => [
                'id' => (int) 29,
                'uuid' => 'f4f629be-e25e-4432-8d97-6b2adcee9065',
                'item_group_id' => null,
                'type' => (int) 2,
                'status' => (int) 30,
                'vessel_id' => (int) 40003,
                'features' => [],
            ],
        ]
    ],

SQL

SELECT *
FROM orders Orders
INNER JOIN users Users ON Users.id = (Orders.user_id)
LEFT JOIN addresses ProjectAddresses ON ProjectAddresses.id = (Orders.address_id)
WHERE (Orders.id = :c0
       OR Orders.postal = :c1
       OR Orders.address LIKE :c2
       OR Orders.city LIKE :c3
       OR Users.first_name = :c4
       OR Users.last_name = :c5
       OR ProjectAddresses.cost_centre = :c6
       OR CONCAT(first_name, last_name) LIKE :c7
       OR Users.first_name IN (:c8)
       OR Users.last_name IN (:c9))

参数为

c1 = 4001 || %40001% || %40001

@ndm 目标是如果有人发送

$freeText == 40003
我必须得到这个对象,其中
vessel_id = 40003
是有效的,但是如果有人发送
$freeText == Test
那么我再次需要相同的结果,因为
first_name == Test
8see 第一个查询),当我在第二个 wuery 中使用匹配/包含时,此结果被删除,因为他只“获取”匹配/包含项目的行...

基本上我想用给定的 $freeText 变量检查 10 多列,如果它匹配,我希望结果出现在我的数据集中(来自两个表)

php cakephp cakephp-3.0
1个回答
3
投票

如果我理解正确,那么您正在寻找左连接过滤器,即左连接

Items
(另外还包含它以供检索),按
Orders
主键分组(以避免重复),然后只需添加将
Items.vessel_id
条件添加到主查询
WHERE
子句中,以便使其也成为
OR
条件。

$query
    ->contain('Items')
    ->leftJoinWith('Items')
    ->where([
        'OR' => [
            'Orders.id' => $freeText,
            // ...
            'Items.vessel_id' => $freeText
        ]
    ])
    ->groupBy('Orders.id');

另请参阅

© www.soinside.com 2019 - 2024. All rights reserved.