我发布了一个我以前以某种方式表示数据的问题,经过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;
感谢任何帮助。
答案 0 :(得分:2)
我猜你的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);