[英]Efficient way to build CSV table from three MySQL tables with PHP
我想使用PHP從數據庫中的數據構建CSV表。 我正在編程的應用程序可以對孩子進行評分。 我的第一張桌子只定義了孩子:
┏━━━━┳━━━━━━┓
┃ ID ┃ name ┃
┡━━━━╇━━━━━━┩
│ 1 │ John │
│ 2 │ Lucy │
│ 3 │ Zara │
└────┴──────┘
第二個定義事件,孩子可以在其中獲得積分
┏━━━━┳━━━━━━━━━━━━┓
┃ ID ┃ date ┃
┡━━━━╇━━━━━━━━━━━━┩
│ 1 │ 2016-12-31 │
│ 2 │ 2017-01-07 │
│ 3 │ 2017-01-14 │
│ 4 │ 2017-01-21 │
└────┴────────────┘
第三個告訴我們在eventID為eventID的事件中獲得childID為childID的點數
┏━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓
┃ ID ┃ eventID ┃ childID ┃ points ┃
┡━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩
│ 1 │ 1 │ 1 │ 21 │
│ 2 │ 1 │ 2 │ 43 │
│ 3 │ 1 │ 3 │ 4 │
│ 4 │ 2 │ 1 │ 8 │
│ 5 │ 2 │ 2 │ 15 │
│ 6 │ 2 │ 3 │ 13 │
│ 7 │ 3 │ 1 │ 34 │
│ 8 │ 3 │ 2 │ 40 │
│ 9 │ 3 │ 3 │ 20 │
│ 10 │ 4 │ 1 │ 3 │
│ 11 │ 4 │ 2 │ 7 │
│ 12 │ 4 │ 3 │ 9 │
└────┴─────────┴─────────┴────────┘
假設我們有C個子事件和E個事件,因此表點具有C * E行。 現在,我想找到構建表的最有效方法,如下所示:
event;John;Lucy;Zara;⋯
2016-12-31; 21; 43; 4;
2017-01-07; 8; 15; 13;
2017-01-14; 34; 40; 20;
2017-01-21; 3; 7; 9;
⋮ ⋱
它也可以被row <-> col交換,但是我的活動比孩子更多。
但是我對數據庫進行C乘E次查詢並不滿意。 我試過用PHP生成冗長而丑陋的查詢,但它基本上也使C乘以E子查詢。 我也有想法如何僅使用E查詢來構建它,但是僅使用一個查詢是不可能的嗎?
考慮條件聚合,在MySQL中,您必須對每個子名稱進行繁瑣的操作。 如果太多(數百個)不可行,請考慮使用PHP動態構建SQL字符串。
SELECT e.date AS `event`,
SUM(CASE WHEN c.name = 'John' THEN j.points ELSE 0 END) As `John`,
SUM(CASE WHEN c.name = 'Lucy' THEN j.points ELSE 0 END) As `Lucy`,
SUM(CASE WHEN c.name = 'Zara' THEN j.points ELSE 0 END) As `Zara`
FROM EventChildJoin j
INNER JOIN ChildTable c
ON j.childID = c.ID
INNER JOIN EventTable e
ON j.eventID = e.ID
GROUP BY e.date
如前所述,由於MySQL沒有交叉表/數據透視圖方法,因此必須在應用程序層構建SQL,然后傳遞到數據庫層進行處理。 這是PHP的示例:
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$database",$username,$password);
# FIRST FETCH
$strSQL = "SELECT DISTINCT name FROM ChildTable";
$STH = $dbh->query($strSQL);
$STH->setFetchMode(PDO::FETCH_ASSOC);
$strSQL = "SELECT e.date AS `event`, ";
while($row = $STH->fetch()) {
$strSQL = $strSQL . " SUM(CASE WHEN c.name = '". row['name'] ."' " .
" THEN j.points ELSE 0 END) As `". row['name'] ."`,";
}
$strSQL = " FROM EventChildJoin j".
" INNER JOIN ChildTable c ".
" ON j.childID = c.ID ".
" INNER JOIN EventTable e ".
" ON j.eventID = e.ID ".
" GROUP BY e.date;";
$strSQL = str_replace(", FROM", " FROM", strSQL) # REMOVE COMMA AFTER LAST COLUMN
# NEXT FETCH
$STH = null;
$STH = $dbh->query($strSQL);
$STH->setFetchMode(PDO::FETCH_ASSOC);
...
}
catch(PDOException $e) {
echo $e->getMessage();
exit;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.