繁体   English   中英

带有动态列的数据透视表

[英]Pivot MySQL Table with Dynamic Columns

我发布了一个问题,在以某种方式表示数据之前,我遇到了一个问题,在2个帖子之后,我能够获得足够的信息来意识到我需要的是带有动态列的数据透视表。

我已经能够创建一个静态枢轴表,但效果很好,但是对于认真的报告来说,它们是没有用的。 到目前为止,这是我所做的:

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

这能够为我提供1月至12月的静态报告,但问题是,如果用户从2015年1月至2017年12月进行搜索,则该表会将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;

任何帮助表示赞赏。

我猜您的month_payment列是DATE (顺便说一句,当您询问SQL问题时,应该发布SHOW CREATE TABLE ,这样我们就不必猜测了)。

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

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM