优化SQL语句(Distinct和left join)CakePhp

时间:2017-02-27 09:27:37

标签: php sql cakephp

所以,我有像这样的cakephp SQL语句

$groupId = $this->request->data['group_id'];
        $placesT = TableRegistry::get('Places');
        $AllPrices = $placesT->find('all')
            ->select(['Places.postal', 'Places.city', 'Places.district', 'Places.state', 'Places.country', 'Prices.delivery_price', 'Prices.retrieval_price', 'Prices.maintenance_price',
                'Prices.edm_price', 'Prices.weighting_price', 'Prices.price_type_fixed_price', 'Prices.price_type_weight_price_per_ton', 'Prices.fee_per_day'])
            ->leftJoin(
                ['Prices' => 'prices'],
                [
                    'Prices.group_id' => $groupId,
                    'Prices.product_id' => $id,
                    'Prices.valid_to >' => (time() * 1000),
                    'Prices.postal = Places.postal',
                ]
                , ['Prices.group_id' => 'integer', 'Prices.product_id' => 'integer', 'Prices.valid_to' => 'integer', 'Prices.postal' => 'integer'])
            ->distinct()
            ->orderAsc('Places.postal')
            ->toArray();

在SQL中看起来像:

SELECT DISTINCT places.postal AS `Places__postal`,
                places.city AS `Places__city`,
                places.district AS `Places__district`,
                places.state AS `Places__state`,
                places.country AS `Places__country`,
                prices.delivery_price AS `Prices__delivery_price`,
                prices.retrieval_price AS `Prices__retrieval_price`,
                prices.maintenance_price AS `Prices__maintenance_price`,
                prices.edm_price AS `Prices__edm_price`,
                prices.weighting_price AS `Prices__weighting_price`,
                prices.price_type_fixed_price AS `Prices__price_type_fixed_price`,
                prices.price_type_weight_price_per_ton AS `Prices__price_type_weight_price_per_ton`,
                prices.fee_per_day AS `Prices__fee_per_day`
FROM places
LEFT JOIN prices ON (prices.group_id = '3'
                            AND prices.product_id = '1'
                            AND prices.valid_to > 1488186767000
                            AND prices.postal = places.postal)
ORDER BY places.postal ASC;

这个说法有效,但是当我有更大的数据量(用于测试)时它不起作用(执行时间太长)。

价格表有100行,而地方表有3k数据。

有什么方法可以让这句话更快?

1 个答案:

答案 0 :(得分:2)

不应在JOIN上使用多个条件。最好让他们在Where条件下。另外,请确保您已将postalproduct_id等列编入索引以查看更好的效果。

SELECT DISTINCT places.postal AS `Places__postal`,
                places.city AS `Places__city`,
                places.district AS `Places__district`,
                places.state AS `Places__state`,
                places.country AS `Places__country`,
                prices.delivery_price AS `Prices__delivery_price`,
                prices.retrieval_price AS `Prices__retrieval_price`,
                prices.maintenance_price AS `Prices__maintenance_price`,
                prices.edm_price AS `Prices__edm_price`,
                prices.weighting_price AS `Prices__weighting_price`,
                prices.price_type_fixed_price AS `Prices__price_type_fixed_price`,
                prices.price_type_weight_price_per_ton AS `Prices__price_type_weight_price_per_ton`,
                prices.fee_per_day AS `Prices__fee_per_day`
FROM places
LEFT JOIN prices ON prices.postal = places.postal
WHERE prices.group_id = '3'
   AND prices.product_id = '1'
   AND prices.valid_to > 1488186767000
ORDER BY places.postal ASC;