将MySQL行转换为视图中的列

时间:2011-05-17 02:31:54

标签: mysql cakephp

我有以下表格:日期,期间,价格,品牌,车辆。

价格模型属于日期和期间。

DB Schema:

CREATE TABLE `days` (
  `id` int(3) NOT NULL AUTO_INCREMENT,
  `low` int(11) NOT NULL DEFAULT '0',
  `high` int(11) DEFAULT '0',
  `brand_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);
CREATE TABLE `periods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `start` date NOT NULL DEFAULT '0000-00-00',
  `finish` date NOT NULL DEFAULT '0000-00-00',
  `brand_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);
CREATE TABLE `brands` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `brand` varchar(255) NOT NULL DEFAULT '',
  `slug` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);
CREATE TABLE `vehicles` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `size_id` int(11) DEFAULT NULL,
  `brand_id` int(11) DEFAULT NULL,
  `slug` varchar(50) NOT NULL,
  `model` varchar(50) DEFAULT NULL,
  `image` varchar(50) DEFAULT NULL,
  `short_specs` text,
  `specs` text,
  `publish` tinyint(1) DEFAULT '1',
  PRIMARY KEY (`id`)
);
CREATE TABLE `prices` (
  `id` int(3) NOT NULL AUTO_INCREMENT,
  `vehicle_id` int(3) NOT NULL DEFAULT '0',
  `day_id` int(3) NOT NULL DEFAULT '0',
  `period_id` int(3) NOT NULL DEFAULT '0',
  `price` decimal(10,2) NOT NULL DEFAULT '0.00',
  PRIMARY KEY (`id`)
);

我在日期和期间模型中使用virtualFields:

// day.php
var $virtualFields = array(
    'name' => "CONCAT(Day.low,IF(Day.high IS NULL, '+', ' to '),IF(Day.high IS NULL, '', Day.high))"
);

// period.php  dates are localized using setLocale and strftime in afterFind()
var $virtualFields = array(
    'name' => "CONCAT(Period.start,'|', Period.finish)"
);
function afterFind($results) {
    foreach ($results as $key => $val) {
        if (isset($val['Period']['name'])) {
            $dates = explode('|',$val['Period']['name']);
            $results[$key]['Period']['name'] = strftime('%d %b %Y',strtotime($dates[0])). ' – ' . strftime('%d %b %Y',strtotime($dates[1]));
        }
    }
    return $results;
}

如果我这样做价格模型:

function price($id) {
    $this->set('prices', $this->find('all',array('conditions' => ('Price.vehicle_id' => $id))));
}

这在视图中显示

Day            Period                      Price
5 - 20          01 May 2011 to 31 Aug 2011  $87.00
21 to 27        01 May 2011 to 31 Aug 2011  $66.00
28+             01 May 2011 to 31 Aug 2011  $63.00
5 - 20          01 Sep 2011 to 30 Sep 2011  $177.00
21 to 27        01 Sep 2011 to 30 Sep 2011  $165.00
28+             01 Sep 2011 to 30 Sep 2011  $155.00
5 - 20          01 Oct 2011 to 31 Oct 2011  $322.00
21 to 27        01 Oct 2011 to 31 Oct 2011  $310.00
28+             01 Oct 2011 to 31 Oct 2011  $300.00

我如何呈现这样的数据?

                           5 - 20 days     21 - 27 days    28+ days
01 May 2011 to 31 Aug 2011  $87.00      $66.00      $63.00
01 Sep 2011 to 30 Sep 2011  $177.00         $165.00         $155.00
01 Oct 2011 to 31 Oct 2011  $322.00         $310.00         $300.00

我一直在努力了解pivot tables,但我很难在CakePHP中做到这一点。任何建议将不胜感激。

2 个答案:

答案 0 :(得分:0)

Mark Story写了一篇名为"Creating easy reports with pivot tables"的博文,很可能对你很有帮助。关键是在查询中为您想要的每个列创建一个单独的字段,然后使用带有IF的字段的表达式来仅选择应该在该列中使用的那些行。

答案 1 :(得分:0)

管理解决问题。这很有用:How to pivot a MySQL entity-attribute-value schema

$prices = $this->Price->find('all',array(
    'conditions'=>array(
        'Price.vehicle_id'=>$id
    ),
    'fields'=>( //GROUP_CONCAT days and prices and separate with colon
        "GROUP_CONCAT( 
            CONCAT_WS(':',
                CONCAT(`Day`.`low`,IF(`Day`.`high` IS NULL, '+', ' to '),IF(`Day`.`high` IS NULL, '', `Day`.`high`)),
                `Price`.`price`
            )
            ORDER BY `Day`.`low`
        ) AS prices, 
        (CONCAT(`Period`.`start`,'|', `Period`.`finish`)) AS `period_name`"
    ),
    'group' => 'Period.id',
    'order' => 'Period.start'
    )
);

$ price看起来像:

array(
    array(
        array(
            'prices' => 'days:price,days:price,days:price,days:price...',
            'period_name' => 'yyy-mm-dd|yyyy-mm-dd'
        ),
        ...