CakePHP - Построение сложного запроса - PullRequest
4 голосов
/ 23 ноября 2011

У меня есть следующий запрос, который я хочу построить, используя CakePHP.Как мне поступить об этом?

        SELECT
            `Artist`.`id`,
            CONCAT_WS(' ', `Person`.`first_name`, `Person`.`last_name`, `Person`.`post_nominal_letters`) AS `name`,
            `Portfolio`.`count`
        FROM
            `people` as `Person`,
            `artists` as `Artist`
        LEFT OUTER JOIN
            (SELECT
                `Product`.`artist_id`,
                 COUNT(DISTINCT `Product`.`id`) AS `count`
            FROM
                `product_availabilities` AS `ProductAvailability`,
                `products` AS `Product`
            LEFT OUTER JOIN
                `order_details` AS `OrderDetail`
            ON
                `Product`.`id` = `OrderDetail`.`product_id`
            LEFT OUTER JOIN
                `orders` AS `Order`
            ON
                `Order`.`id` = `OrderDetail`.`order_id`
            WHERE
                `ProductAvailability`.`id` = `Product`.`product_availability_id`
            AND
                `Product`.`online` = true
            AND
                (`ProductAvailability`.`name` = 'For sale')
                OR
                    ((`ProductAvailability`.`name` = 'Sold') AND (DATEDIFF(now(),`Order`.`order_date`) <= 30))
            GROUP BY
                `Product`.`artist_id`)
        AS
            `Portfolio`
        ON
            `Artist`.`id` = `Portfolio`.`artist_id`
        WHERE
            `Artist`.`person_id` = `Person`.`id`
        AND
            `Artist`.`online` = true
        GROUP BY
            `Artist`.`id`
        ORDER BY
            `Person`.`last_name`, `Person`.`first_name`;

Ответы [ 4 ]

1 голос
/ 13 февраля 2013

Я думаю, что модель это Artist, и она имеет отношение к отношениям, тогда вы можете использовать CakePHP ORM таким образом и иметь много с портфелем

сначала вы должны исказить связь между исполнителем и портфолио

$this->Artist->unbindModel(array('hasMany'=>array('Portfolio')));

и затем Постройте отношения

$this->Artist->bindModel(array('hasOne'=>array('Portfolio')));

Наконец, вы должны создать другие отношения

$this->Artist->bindModel(array(
'belongsTo'=>array(
'Product'=>array(
 'clasName'=>'Product',
 'foreignKey'=> false,
 'conditions'=>'Product.id = Artist.product_id'
 ),
 'ProductAvaibility'=>array(
 'clasName'=>'ProductAvaibility',
 'foreignKey'=> false,
 'conditions'=>'ProductAvaibility.id = Product.product_avaibility_id'
 ),
 'OrderDetail'=>array(
 'clasName'=>'OrderDetail',
 'foreignKey'=> false,
 'conditions'=>'Product.id = OrderDetail.product_id'
 ),
 'Order'=>array(
 'clasName'=>'Order',
 'foreignKey'=> false,
 'conditions'=>'Order.id = OrderDetail.order_id'
 ),
)
));

Теперь, когда отношенияготово, вы могли бы сделать свою находку

$this->Artist->find('all', array(
'conditions'=>array(
'Artist.online'=>true
),
'group'=>array(
'Artist.id'
),
'order'=>array(
'Person.last_name', 
'Person.first_name', 
)
))

Я надеюсь, что это может быть полезно для вас

0 голосов
/ 23 ноября 2011

Вы можете использовать метод query, но этот метод рассматривается как последнее средство, когда find или любой другой удобный метод не достаточен.

Но также можно вручную указать соединения в методе Cake find, см. Кулинарную книгу .Я не совсем уверен, но я считаю, что вложенные объединения также поддерживаются.CONCAT_WS можно просто вызвать с соответствующими полями в свойстве field метода find.

0 голосов
/ 24 ноября 2011

Не пытайтесь построить этот запрос, используя ORM. Это будет катастрофа в замедленном темпе.

Вместо этого вы должны попытаться выполнить этот запрос как можно ближе к металлу. Я не знаком с API CakePHP (так как я склонен избегать его, как черная чума), но вы должны быть в состоянии создать Model, который не связан с ActiveRecord и, скорее всего, имеет доступ к чему-либо похожему на оболочку PDO. Используйте это, чтобы выполнить запрос и отобразить результаты в переменные.


Тем не менее, вы, возможно, захотите проверить свой запрос (у вас, кажется, есть какая-то навязчивая цитата о болезни ). Одним из улучшений, которое вы могли бы сделать, было бы прекращение использования id столбцов в таблицах.

Эта целая установка может действительно выиграть от создания еще одного столбца в таблице Artists: portfolio_size. Который вы можете обновлять каждый раз, когда он должен быть изменен. Да, это нормализует вашу таблицу, но также сделает этот запрос тривиальным и быстрым, с незначительными затратами в других местах.


Что касается имен столбцов, если у таблицы Artists есть идентификатор, сохраните его в столбце artist_id, а если у Products есть внешний ключ, ссылающийся на Artists.artist_id, то назовите его тоже artist_id. Одна и та же вещь должна иметь одинаковое имя во всей вашей базе данных. Это дополнительно позволит вам использовать в операторе SQL USING. Вот небольшой пример:

SELECT 
   Users.name
   Users.email
FROM Users
LEFT JOIN GroupUsers USING (user_id)
LEFT JOIN Groups USING (group_id)
WHERE Groups.name = 'wheel'

Я полагаю, что этот запрос не нуждается в объяснении, так как он представляет собой простое отношение многих к множеству между пользователями и группами.

0 голосов
/ 23 ноября 2011

Вы должны поместить его в свою модель. Если вы еще не читали, я предлагаю вам прочитать о тощих контроллерах и толстых моделях .

class YourModel extends AppModel {

    public function getArtistsAndPortfolioCounts() {
        return $this->query("SELECT ... ");
    }

}

Итак, в вашем контроллере:

class ArtistsControllre extends AppController {
    public function yourAction() {
        debug($this->YourModel->getArtistsAndPortfolioCounts());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...