我想使用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
的事件中有多少积分带有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;
⋮ ⋱
它也可以是行< - > col swapped,但我发现的事件多于儿童。
但我对让C次E查询到数据库感到不舒服。我尝试用PHP生成冗长而丑陋的查询,但它基本上也使C次E子查询。我也知道如何只使用E查询来构建它,但是只有一个查询是不可能的?
答案 0 :(得分:0)
考虑条件聚合,在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;
}