You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于student-subject-marks表生成指定结果(分数不硬编码)

数据表转换解决方案

需求说明

需要将student-subject-marks的行式数据表(每行对应学生某一科目的分数)转换为列式结构(每列对应一个科目,每行对应学生的所有科目分数),且实现过程中不得硬编码科目或分数相关固定值。

原始数据表结构示例

student_idstudent_namesubjectmarks
1AliceMath85
1AliceScience90
1AliceEnglish78
2BobMath92
2BobScience88
2BobEnglish80

目标数据表结构示例

student_idstudent_nameMathScienceEnglish
1Alice859078
2Bob928880

实现方案(以SQL为例)

由于不能硬编码科目,需使用动态SQL自动识别所有科目并完成列转行操作。

MySQL 实现

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN subject = ''',
      subject,
      ''' THEN marks END) AS `',
      subject,
      '`'
    )
  ) INTO @sql
FROM student_subject_marks;

SET @sql = CONCAT('SELECT student_id, student_name, ', @sql, ' 
                  FROM student_subject_marks 
                  GROUP BY student_id, student_name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

PostgreSQL 实现

-- 方式1:以JSON格式返回科目与分数
CREATE OR REPLACE FUNCTION pivot_student_marks()
RETURNS TABLE (student_id INT, student_name VARCHAR, subjects JSONB) AS $$
BEGIN
  RETURN QUERY
  SELECT 
    student_id,
    student_name,
    JSONB_OBJECT_AGG(subject, marks) AS subjects
  FROM student_subject_marks
  GROUP BY student_id, student_name;
END;
$$ LANGUAGE plpgsql;

-- 调用函数获取结果
SELECT * FROM pivot_student_marks();

-- 方式2:动态展开为列(PostgreSQL 11+ 支持)
DO $$
DECLARE
  cols TEXT;
BEGIN
  SELECT string_agg(DISTINCT quote_ident(subject), ', ') INTO cols
  FROM student_subject_marks;
  
  EXECUTE format('
    SELECT student_id, student_name, %s
    FROM student_subject_marks
    PIVOT (MAX(marks) FOR subject IN (%s)) AS p
  ', cols, cols);
END $$;

关键注意点

  • 动态SQL会自动读取表中所有subject值,无需手动硬编码任何科目或分数
  • 分组时需确保student_id+student_name是唯一标识学生的组合键
  • 若同一学生同一科目存在多条记录,可根据需求替换MAX()为AVG()或SUM()等聚合函数

内容的提问来源于stack exchange,提问作者Dharmesh Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:05:27