2017-09-05 65 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

剛上班,會測試並讓你知道 –