MySQL连接3个测验表并按属性/用户计算总计的实现方案
合并测验表并导出CSV的完整方案
嘿,看起来你需要把三个测验相关表做联合查询,按用户+问题属性计算总计,最后用PHP导出成CSV对吧?先补个小前提:你提到了三个表,但只描述了users和questions——我猜第三个肯定是存储用户回答的表(比如叫answers,字段大概是user_id、question_id、score,用来记录用户对每个问题的得分),如果你的表名或字段不一样,后面对应调整就行~
1. MySQL查询:按用户+属性计算总计
我们的核心目标是拿到每个用户对应每个问题属性的总计数据(比如总分、回答数量,这里先以总分举例)。用JOIN关联三个表,再按用户和属性分组即可:
SELECT u.id AS user_id, u.name, u.email, q.attribute, -- 用COALESCE把空值转成0,避免没有回答的属性出现NULL COALESCE(SUM(a.score), 0) AS total_score FROM users u -- LEFT JOIN确保即使用户没回答某类问题,也会出现在结果里 LEFT JOIN answers a ON u.id = a.user_id LEFT JOIN questions q ON a.question_id = q.id GROUP BY u.id, u.name, u.email, q.attribute ORDER BY u.id, q.attribute;
灵活调整点:
- 如果要统计回答的问题数量,把
SUM(a.score)换成COUNT(a.id)就行; - 如果要统计平均得分,换成
AVG(a.score); - 如果第三个表不是
answers(比如叫responses),记得替换表名和关联字段。
2. PHP导出CSV的实现
拿到查询结果后,用PHP的内置CSV函数就能快速生成并下载文件,不需要额外依赖:
<?php // 数据库连接信息,换成你自己的 $db_host = 'localhost'; $db_name = 'your_database'; $db_user = 'your_username'; $db_pass = 'your_password'; try { // 用PDO连接数据库,比mysqli更安全简洁 $pdo = new PDO( "mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] ); // 执行上面的查询 $query = "SELECT u.id AS user_id, u.name, u.email, q.attribute, COALESCE(SUM(a.score), 0) AS total_score FROM users u LEFT JOIN answers a ON u.id = a.user_id LEFT JOIN questions q ON a.question_id = q.id GROUP BY u.id, u.name, u.email, q.attribute ORDER BY u.id, q.attribute"; $stmt = $pdo->query($query); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); // 设置HTTP响应头,让浏览器识别为CSV文件并触发下载 header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=quiz_attribute_totals.csv'); // 打开输出流,直接输出到浏览器 $output = fopen('php://output', 'w'); // 先写入CSV表头 fputcsv($output, ['用户ID', '姓名', '邮箱', '问题属性', '总计得分']); // 逐行写入数据 foreach ($data as $row) { fputcsv($output, $row); } fclose($output); exit; } catch (PDOException $e) { die("数据库连接/查询出错: " . $e->getMessage()); } ?>
额外说明:
- 如果想把CSV保存到服务器而不是让用户下载,把
fopen('php://output', 'w')换成fopen('/your/server/path/quiz_results.csv', 'w')即可; - 如果你的问题属性对应的总计不是得分,比如只是统计是否回答,把查询里的聚合函数换成
COUNT(a.id)就能得到每个属性下用户回答的问题数。
3. 适配不同表结构的例子
假设你的第三个表叫responses,只有user_id和question_id(只记录用户回答过这个问题,没有得分),那查询可以改成:
SELECT u.id AS user_id, u.name, u.email, q.attribute, COUNT(a.id) AS answered_question_count FROM users u LEFT JOIN responses a ON u.id = a.user_id LEFT JOIN questions q ON a.question_id = q.id GROUP BY u.id, u.name, u.email, q.attribute ORDER BY u.id, q.attribute;
这样就能得到每个用户每个属性下回答过的问题数量了。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

