CakePHP 3对联合查询的结果进行分页

时间:2019-04-17 15:53:46

标签: cakephp cakephp-3.0 union paginate

我有两个桌子。第一个具有主要产品数据,另一个具有这些产品的辅助描述,通过第二个表上的products_id外键链接。

我已经创建了SQL,一切看起来都不错。但是,当我用相同的结果SQL代码转换为CakePHP 3的ORM时,它出现了一个大问题:每个页面都显示了第二个数据表的辅助描述。

在首页分页索引中,拥有主要产品的索引按预期工作。首先,显示主要产品,然后,描述显示辅助表数据中的辅助描述。但是,当我单击以查看下一页时,当我期望从此表数据中获得任何收益时,这些次要产品就在那里。

仅当该页面上有主要产品时,我才需要显示这些辅助描述,而该产品不存在时,则不会显示该表中的任何记录。就像在SQL脚本结果中一样。

在此SQL脚本上,您可以看到我需要的内容:

    (SELECT 
        Products.id, 
        (null) AS product_titles_id,
        (Products.title) AS title_,
        Products.product_groups_id, 
        Products.product_types_id, 
        Products.code, 
        Products.title, 
        Products.ean, 
        Products.ncm, 
        Products.obs, 
        Products.minimum, 
        Products.maximum,
        ProductTypes.id,
        ProductTypes.code,
        ProductTypes.title,
        ProductTypes.calc_cost,
        ProductGroups.id,
        ProductGroups.code,
        ProductGroups.title
    FROM `products` Products
       LEFT JOIN `product_groups` ProductGroups ON Products.product_groups_id = ProductGroups.id
       LEFT JOIN `product_types` ProductTypes ON Products.product_types_id = ProductTypes.id)

    UNION

    (SELECT 
        Products.id,
        ProductTitles.id AS product_titles_id, 
        (ProductTitles.title) AS title_,
        Products.product_groups_id, 
        Products.product_types_id, 
        -- ProductTitles.products_id, 
        ProductTitles.code, 
        ProductTitles.title, 
        Products.ean, 
        Products.ncm, 
        ProductTitles.obs,
        Products.minimum, 
        Products.maximum,
        ProductTypes.id,
        ProductTypes.code,
        ProductTypes.title,
        ProductTypes.calc_cost,
        ProductGroups.id,
        ProductGroups.code,
        ProductGroups.title
    FROM `product_titles` ProductTitles
       LEFT JOIN `products` Products ON products.id = ProductTitles.products_id
       LEFT JOIN `product_groups` ProductGroups ON Products.product_groups_id = ProductGroups.id
       LEFT JOIN `product_types` ProductTypes ON Products.product_types_id = ProductTypes.id)
    ORDER BY title_

这是该SQL脚本的结果:

    id  product_titles_id   title_
    0080    NULL              SUPORTE DE PRESSAO
    7545    NULL              BA RET.
    3177    NULL              CORT RDX
    3177    17                EMEN RDX (secondary description)
    3177    18                PART RDX (secondary description)
    6623    NULL              LATAO CALCO CALIB.
    8079    NULL              TRANSM DE PRESSAO
    4242    NULL              GY 6/6 P.U CORAL

这是我在CakePHP ORM脚本上所做的:

    //Main table of products
    $qry_products = $this->Products->findByParametersId('85')
            ->select(['Products.id', 'product_titles_id' => 'null', 
                      'title_' => 'Products.title', 
                      'Products.product_groups_id', 
                      'Products.product_types_id', 
                      'Products.code', 'Products.title', 
                      'Products.ean', 'Products.ncm', 
                      'Products.obs', 'Products.minimum', 
                      'Products.maximum', 'ProductTypes.id', 
                      'ProductTypes.code', 'ProductTypes.title', 
                      'ProductTypes.calc_cost', 'ProductGroups.id', 
                      'ProductGroups.code', 'ProductGroups.title', 
                      'ProductTitles' => '0'
                     ])
            ->where($where)
            ->join([
              'ProductGroups' => ['table' => 'product_groups',
                                  'type'       => 'LEFT',
                                  'conditions' => 'Products.product_groups_id = ProductGroups.id'
                                 ],
              'ProductTypes'  => ['table'      => 'product_types',
                                  'type'       => 'LEFT',
                                  'conditions' => 'Products.product_types_id = ProductTypes.id'
                                 ]
                   ])
             ->limit(20);

    //Secondary table of products' descriptions:
    $qry_productTitles = $this->ProductTitles->findByParametersId('85')
             ->select(['Products.id', 
                       'product_titles_id' =>                  'ProductTitles.id', 
                       'title_' => 'ProductTitles.title', 
                       'product_groups_id' => 'Products.product_groups_id', 
                       'product_types_id' => 'Products.product_types_id', 
                       'ProductTitles.code', 'ProductTitles.title',
                       'ean' => 'Products.ean', 
                       'ncm' => 'Products.ncm', 
                       'obs' => 'Products.obs', 
                       'minimum' => 'Products.minimum', 
                       'maximum' => 'Products.maximum',
                       'ProductTypes.id', 'ProductTypes.code', 
                       'ProductTypes.title',                            
                       'ProductTypes.calc_cost', 
                       'ProductGroups.id', 'ProductGroups.code', 
                       'ProductGroups.title', 
                       'ProductTitles' => '1'
                      ])
             ->join([
      'Products' => ['table'      => 'products',
                     'type'       => 'LEFT',
                     'conditions' => 'ProductTitles.products_id = Products.id'
                    ],
      'ProductGroups' => ['table'      => 'product_groups',
                          'type'       => 'LEFT',
                          'conditions' => 'Products.product_groups_id = ProductGroups.id'
                         ],
      'ProductTypes' => ['table'      => 'product_types',
                         'type'       => 'LEFT',
                         'conditions' => 'Products.product_types_id = ProductTypes.id'
                        ]
    ]);

    //Union these two tables and put some where conditions and ordanation:
    $products = $qry_products->union($qry_productTitles)
                             ->where($where)
                             ->epilog('ORDER BY title_');
                             //->order(['title_ ASC']);

这是从CakePHP ORM生成的SQL结果:

    'sql' => '
    (SELECT Products.id AS `Products__id`, 
     null AS `product_titles_id`, Products.title AS `title_`, 
     Products.product_groups_id AS `Products__product_groups_id`, 
     Products.product_types_id AS `Products__product_types_id`, 
     Products.code AS `Products__code`, 
     Products.title AS `Products__title`, 
     Products.ean AS `Products__ean`, 
     Products.ncm AS `Products__ncm`, 
     Products.obs AS `Products__obs`, 
     Products.minimum AS `Products__minimum`, 
     Products.maximum AS `Products__maximum`, 
     ProductTypes.id AS `ProductTypes__id`, 
     ProductTypes.code AS `ProductTypes__code`, 
     ProductTypes.title AS `ProductTypes__title`,        
     ProductTypes.calc_cost AS `ProductTypes__calc_cost`, 
     ProductGroups.id AS `ProductGroups__id`, 
     ProductGroups.code AS `ProductGroups__code`, 
     ProductGroups.title AS `ProductGroups__title`, 
     0 AS `ProductTitles` 
    FROM products Products 
    LEFT JOIN product_groups ProductGroups ON Products.product_groups_id = ProductGroups.id 
    LEFT JOIN product_types ProductTypes ON Products.product_types_id = ProductTypes.id 
    ORDER BY title_ LIMIT 20)

    UNION 

    (SELECT Products.id AS `Products__id`, 
     ProductTitles.id AS `product_titles_id`, 
     ProductTitles.title AS `title_`,  
     Products.product_groups_id AS `product_groups_id`, 
     Products.product_types_id AS `product_types_id`, 
     ProductTitles.code AS `ProductTitles__code`, 
     ProductTitles.title AS `ProductTitles__title`, 
     Products.ean AS `ean`, Products.ncm AS `ncm`, 
     Products.obs AS `obs`, Products.minimum AS `minimum`, 
     Products.maximum AS `maximum`, 
     ProductTypes.id AS `ProductTypes__id`, 
     ProductTypes.code AS `ProductTypes__code`, 
     ProductTypes.title AS `ProductTypes__title`, 
     ProductTypes.calc_cost AS `ProductTypes__calc_cost`, 
     ProductGroups.id AS `ProductGroups__id`, 
     ProductGroups.code AS `ProductGroups__code`, 
     ProductGroups.title AS `ProductGroups__title`, 
     1 AS `ProductTitles` 
    FROM product_titles ProductTitles 
    LEFT JOIN products Products ON ProductTitles.products_id = Products.id 
    LEFT JOIN product_groups ProductGroups ON Products.product_groups_id = ProductGroups.id 
    LEFT JOIN product_types ProductTypes ON Products.product_types_id = ProductTypes.id) 

    ORDER BY title_',

1 个答案:

答案 0 :(得分:0)

使用以下代码解决了问题:

$products_union = "((SELECT 
                       Products.id AS `id`, 
                       Products.product_groups_id, 
                       Products.product_types_id, 
                       Products.code AS `code`, 
                       Products.title AS `title`, 
                       Products.ean AS `ean`, 
                       Products.ncm AS `ncm`, 
                       Products.obs AS `obs`, 
                       Products.minimum AS `minimum`, 
                       Products.maximum AS `maximum`,
                       ProductTypes.id AS `ProductTypes__id`,
                       ProductTypes.code AS `ProductTypes__code`,
                       ProductTypes.title AS `ProductTypes__title`,
                       ProductTypes.calc_cost AS `ProductTypes__calc_cost`,
                       ProductGroups.id AS `ProductGroups__id`,
                       ProductGroups.code AS `ProductGroups__code`,
                       ProductGroups.title AS `ProductGroups__title`
                     FROM `products` Products
                     LEFT JOIN `product_groups` ProductGroups 
                            ON Products.product_groups_id = ProductGroups.id
                     LEFT JOIN `product_types` ProductTypes 
                            ON Products.product_types_id = ProductTypes.id)

                     UNION ALL

                     (SELECT 
                        Products.id AS `id`, 
                        Products.product_groups_id, 
                        Products.product_types_id, 
                        ProductTitles.code AS `code`, 
                        ProductTitles.title AS `title`, 
                        Products.ean AS `ean`, 
                        Products.ncm AS `ncm`, 
                        ProductTitles.obs AS `obs`, 
                        Products.minimum AS `minimum`, 
                        Products.maximum AS `maximum`,
                        ProductTypes.id AS `ProductTypes__id`,
                        ProductTypes.code AS `ProductTypes__code`,
                        ProductTypes.title AS `ProductTypes__title`,
                        ProductTypes.calc_cost AS `ProductTypes__calc_cost`,
                        ProductGroups.id AS `ProductGroups__id`,
                        ProductGroups.code AS `ProductGroups__code`,
                        ProductGroups.title AS `ProductGroups__title`
                      FROM `product_titles` ProductTitles
                      LEFT JOIN `products` Products 
                            ON Products.id = ProductTitles.products_id
                      LEFT JOIN `product_groups` ProductGroups 
                            ON Products.product_groups_id = ProductGroups.id
                      LEFT JOIN `product_types` ProductTypes 
                            ON Products.product_types_id = ProductTypes.id
                        ))";

    $products = $this->Products->find('all')
                               ->from([$this->Products->alias() => $products_union])
                               ->contain(['ProductTypes', 'ProductGroups'])
                               ->where($where)
                               ->order(['Products.title']);

现在,“ LIMIT”和“ OFFSET”在正确的位置。我仍然使用3.4 CakePHP版本。