2017-09-05 46 views
1

我发布了一个问题,我之前曾以某种方式表示数据,之后有2篇文章,我能够获得足够的信息来实现我需要的是带有动态列的数据透视表。支持动态列的MySQL表格

我已经能够创建一个效果很好的静态数据透视表,但对于严重的报告他们没用。以下是我迄今所做的:

select `title` as `Payment Method`, 
    sum(case when MONTH(t1.`month_payment`) = 1 then amount else 0 end) Jan, 
    sum(case when MONTH(t1.`month_payment`) = 2 then amount else 0 end) Feb, 
    sum(case when MONTH(t1.`month_payment`) = 3 then amount else 0 end) Mar, 
    sum(case when MONTH(t1.`month_payment`) = 4 then amount else 0 end) Apr, 
    sum(case when MONTH(t1.`month_payment`) = 5 then amount else 0 end) May, 
    sum(case when MONTH(t1.`month_payment`) = 6 then amount else 0 end) Jun, 
    sum(case when MONTH(t1.`month_payment`) = 7 then amount else 0 end) Jul, 
    sum(case when MONTH(t1.`month_payment`) = 8 then amount else 0 end) Aug, 
    sum(case when MONTH(t1.`month_payment`) = 9 then amount else 0 end) Sep, 
    sum(case when MONTH(t1.`month_payment`) = 10 then amount else 0 end) Oct, 
    sum(case when MONTH(t1.`month_payment`) = 11 then amount else 0 end) Nov, 
    sum(case when MONTH(t1.`month_payment`) = 12 then amount else 0 end) `Dec` 

from record_payment t1 
join setting_payment_method ON 
setting_payment_method.id = t1.method_id 
where `month_payment` >= '$date_from' 
    and `month_payment` <= '$date_to' 
group by title with rollup 

这是能够让我从一月静态报告,十二月,但问题是,如果从2015年1月用户搜索到2017年十二月,该表将总结和汇总2015年1月,2016年和2017年全部进入显示给用户的1月份是错误的。

我还制作了年报静态支点:

select `title` as `Payment Method`, 
    sum(case when YEAR(t1.`month_payment`) = 2013 then amount else 0 end) `2013`, 
    sum(case when YEAR(t1.`month_payment`) = 2014 then amount else 0 end) `2014`, 
    sum(case when YEAR(t1.`month_payment`) = 2015 then amount else 0 end) `2015`, 
    sum(case when YEAR(t1.`month_payment`) = 2016 then amount else 0 end) `2016`, 
    sum(case when YEAR(t1.`month_payment`) = 2017 then amount else 0 end) `2017` 

from record_payment t1 
join setting_payment_method ON 
setting_payment_method.id = t1.method_id 
where `month_payment` >= '$date_from' 
    and `month_payment` <= '$date_to' 
group by title with rollup 

,但有时你需要报告,给你一年的击穿几个月长的时间(如12岁以上),所以你可以看到趋势。

我尝试做一个自动旋转并非如此成功:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'sum(case when month_payment = ''', 
     month_payment, 
     ''' then amount end) AS `', 
     month_payment, 
     '`' 
    ) 
) INTO @sql 
FROM record_payment; 

SET @sql = CONCAT('SELECT `title` as `Payment Method`, ', @sql, ' FROM record_payment t1 
join setting_payment_method ON 
setting_payment_method.id = t1.method_id 
where `month_payment` >= '$date_from' 
    and `month_payment` <= '$date_to' 
group by title with rollup'); 
PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

任何帮助表示赞赏。

+0

你是否试图在调用'mysqli_query()'的时候完成所有的事情?您无法通过一次调用完成多个语句,您需要为每个语句单独调用一次。 – Barmar

+0

我建议把它放到存储过程中。 – Barmar

+0

您的第一个查询中需要相同的WHERE条件。但我只会按'title,year'进行分组,并将结果格式化为PHP。 –

回答

2

我想你的month_payment列是DATE(顺便说一句,应该发布SHOW CREATE TABLE当你问SQL问题,所以我们不必猜测)。

但是,您的第一个查询不格式化到年/月。它也不限制日期范围。

SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM month_payment) = ', 
     EXTRACT(YEAR_MONTH FROM month_payment), 
     ' THEN AMOUNT END) AS `', 
     EXTRACT(YEAR_MONTH FROM month_payment), 
     '`' 
    ) 
) INTO @sql 
FROM record_payment 
WHERE month_payment BETWEEN ? AND ? 

https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_extract


尽管Barmar的建议,我们没有理由把这个存储过程。你用PHP标记了你的问题,你可以在PHP中做到这一点很好:

<?php 

...get a PDO connection... 

$sql = " 
    SELECT 
     GROUP_CONCAT(DISTINCT 
     CONCAT(
      'SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM month_payment) = ', 
      EXTRACT(YEAR_MONTH FROM month_payment), 
      ' THEN AMOUNT END) AS `', 
      EXTRACT(YEAR_MONTH FROM month_payment), 
      '`' 
     ) 
    ) AS `pivot_columns` 
    FROM record_payment 
    WHERE month_payment BETWEEN ? AND ? 
"; 
$stmt = $pdo->prepare($sql); 
$date_from = '2017-01-01'; 
$date_to = '2017-08-01'; 
$stmt->execute([$date_from, $date_to]); 
$row = $stmt->fetch(); 
$stmt->closeCursor(); 
$pivot_columns = $row['pivot_columns']; 

$sql = " 
    SELECT title AS `Payment Method`, {$pivot_columns} 
    FROM record_payment t1 
    JOIN setting_payment_method spm ON spm.id = t1.method_id 
    WHERE month_payment BETWEEN ? AND ? 
    GROUP BY title WITH ROLLUP 
"; 
echo $sql; 
$stmt = $pdo->prepare($sql); 
$stmt->execute([$date_from, $date_to]); 
$results = $stmt->fetchAll(); 
$stmt->closeCursor(); 

print_r($results); 
+0

是的,month_payment是日期数据类型。 *感谢您的提示。所以在我的存储过程中,我的IN参数是我的2个日期,但是我对执行语句有点困惑。我在哪个阶段调用存储过程?通常你可以像这样调用过程... SET @ p0 ='2015-01-01'; SET @ p1 ='2017-01-01'; CALL'payment_summary'(@ p0,@ p1); –

+0

@EnochS查看我上面添加到我的答案中的PHP示例。 –

+0

刚上班,会测试并让你知道 –