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

时间:2017-07-17 11:59:08

标签: cakephp cakephp-3.0

如何在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 8请求第一个查询)而在第二个wuery我使用匹配/包含此结果被删除,因为他只“获取”匹配/包含项目的行...

基本上我想用给定的$ freeText变量检查10+列,如果匹配,我希望这会导致我的数据集(来自两个表)

1 个答案:

答案 0 :(得分: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');

另见