带有动态列的 Select 语句,其中这些列是另一个表中的行

Nar*_*_CH 3 mysql

我想写一个带有一些固定列和动态列的选择语句。这里的动态列名称是另一个表中的行。

我试过这个,但得到错误。请告诉我我的错误在哪里

set @sql=(Select subject from tbl_subjects where C_Id=22);
SELECT 
    ta.rollno,
    ta.StdNm,
    tc.C_Name,
    @sql
FROM
    tbl_cmarks tm,
    tbl_admission ta,
    tbl_classes tc
WHERE
    tm.Cid = tc.C_Id
        AND ta.rollno = tm.rollno
        AND tm.Cid = 22 and tm.Examid=9 
Run Code Online (Sandbox Code Playgroud)

Mysql 显示:

错误代码:1242。子查询返回多于 1 行

谁能告诉我如何在mysql中做到这一点?

Tar*_*ryn 12

查看您的表结构,我建议您将设计更改为标准化的设计。例如:

create table tbl_subjects
(
  sub_id int,
  subject_name varchar(25)
);

create table tbl_cmarks
(
  c_id int,
  examid int,
  rollno int,
  sub_id int,
  mark int
);
Run Code Online (Sandbox Code Playgroud)

使用类似于上面的内容将允许您添加新主题而无需更改您的表格。然后,您只需加入 上的表格sub_id即可获得每个班级的科目列表。

select ta.rollno,ta.StdNm,tc.C_Name,
  tm.mark,
  s.subject
FROM tbl_cmarks tm
INNER JOIN tbl_classes tc
  ON tm.Cid = tc.C_Id
INNER JOIN tbl_admission ta
  ON ta.rollno = tm.rollno
INNER JOIN tbl_subjects s
  on tm.sub_id = s.sub_id
where tm.Cid = 22 
  and tm.Examid=9;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo。以上将为您提供行中的结果,但您可以轻松地应用带有 CASE 表达式的聚合函数将数据转换为列。类似于以下内容:

select ta.rollno,
  ta.StdNm,
  tc.C_Name,
  max(case when s.subject = 'English' then tm.mark end) Emglish,
  max(case when s.subject = 'Physics' then tm.mark end) Physics
FROM tbl_cmarks tm
INNER JOIN tbl_classes tc
  ON tm.Cid = tc.C_Id
INNER JOIN tbl_admission ta
  ON ta.rollno = tm.rollno
INNER JOIN tbl_subjects s
  on tm.sub_id = s.sub_id
where tm.Cid = 22 
  and tm.Examid=9
group by  ta.rollno, ta.StdNm, tc.C_Name;
Run Code Online (Sandbox Code Playgroud)

演示

但是如果你不改变你当前的表结构,如果你不知道你将要返回的列,那么你将不得不实现一个准备好的语句来生成动态 SQL。

首先,您将创建类列表:

set @sqlList = null;
set @query = null;

SELECT
  GROUP_CONCAT(concat('tm.', subject)) 
INTO @sqlList
FROM tbl_subjects
where C_Id=22;
Run Code Online (Sandbox Code Playgroud)

演示。这将为您提供每个c_id. 获得类列表后,您可以将其添加到 sql 字符串的其余部分,以便完整代码为:

set @sqlList = null;
set @query = null;

SELECT
  GROUP_CONCAT(concat('tm.', subject)) 
INTO @sqlList
FROM tbl_subjects
where C_Id=22;

SET @query 
  = CONCAT('SELECT ta.rollno,ta.StdNm,tc.C_Name, ', @sqlList, ' 
            FROM tbl_cmarks tm
            INNER JOIN tbl_classes tc
              ON tm.Cid = tc.C_Id
            INNER JOIN tbl_admission ta
              ON ta.rollno = tm.rollno
            where tm.Cid = 22 
              and tm.Examid=9');

PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Run Code Online (Sandbox Code Playgroud)

参见SQL Fiddle with Demo