我想使用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`;
答案 0 :(得分:1)
我认为该模型是艺术家并且它与belongsTo有关系,那么你可以用这种方式使用CakePHP ORM并且hasMany with Portfolio
首先,你要破坏艺术家与作品集之间的关系
$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',
)
))
我希望它对你有用
答案 1 :(得分:0)
您应该将它放在模型中。如果您还没有阅读,我建议您阅读skinny controllers and fat models。
class YourModel extends AppModel {
public function getArtistsAndPortfolioCounts() {
return $this->query("SELECT ... ");
}
}
所以在你的控制器中:
class ArtistsControllre extends AppController {
public function yourAction() {
debug($this->YourModel->getArtistsAndPortfolioCounts());
}
}
答案 2 :(得分:0)
您可以使用query
方法,但当find
或任何其他便利方法不够时,该方法将被视为最后的手段。
但也可以在Cake find
方法see the cookbook中手动指定联接。我不完全确定,但我相信也支持嵌套连接。可以使用相关字段在find方法的CONCAT_WS
属性中调用field
。
答案 3 :(得分:0)
不要尝试使用ORM构建该查询。这将是一场慢动作的灾难。
相反,你应该尝试尽可能“接近金属”。我不熟悉CakePHP的API(因为我倾向于像黑瘟一样避免它),但你应该能够创建一个与ActiveRecord无关的Model
,并且很可能可以访问类似于PDO包装器的任何内容。用它来执行查询并将结果映射到变量。
那就是说,你可能想检查你的查询(你似乎有一些强迫性的引用疾病)。您可以做的一项改进是停止在表中使用id
列。
这整个设置确实可以从Artists表中另一列的创建中受益:portfolio_size
。每次更改时都可以更新。是的,它会使你的桌子不规范化,但它也会使这个查询变得微不足道并且快速,而其他地方的成本很低。
对于列的名称,如果表Artists
具有ID,则将其保留在列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'
我认为此查询不需要解释,因为它是用户和组之间的简单多对多关系。