在MySQL中动态地将行转换为列

在MySQL中动态地将行转换为列,mysql,sql,yii,pivot,Mysql,Sql,Yii,Pivot,我对MySQL有问题。我希望有基于行的动态列。详情如下 SELECT `marks`.`id` , `marks`.`studentID` , `marks`.`subjectID` , `marks`.`mark` FROM `Mark` `marks` LEFT OUTER JOIN `Student` `students` ON ( `students`.`id` = `marks`.`studentID` ) WHERE ( `students`.`classID` =1 ) LIMIT

我对MySQL有问题。我希望有基于行的动态列。详情如下

SELECT `marks`.`id` , `marks`.`studentID` , `marks`.`subjectID` , `marks`.`mark`
FROM `Mark` `marks`
LEFT OUTER JOIN `Student` `students` ON ( `students`.`id` = `marks`.`studentID` )
WHERE (
`students`.`classID` =1
)
LIMIT 0 , 30

My Output is 
+----+-----------+-----------+------+
| id | studentID | subjectID | mark |
+----+-----------+-----------+------+
|  1 |         1 |         1 |   20 |
|  2 |         1 |         2 |   36 |
|  3 |         2 |         1 |   47 |
|  4 |         2 |         2 |   43 |
+----+-----------+-----------+------+
4 rows in set (0.00 sec)


Output I need is 

+----+-----------+-----------+-----------+
| id | studentID | subject_1 | subject_2 |
+----+-----------+-----------+-----------+
|  1 |         1 |        20 |        36 |
|  2 |         2 |        47 |        43 |
+----+-----------+-----------+-----------+
4 rows in set (0.00 sec)
受试者的数量取决于受试者表中的条目。我只需要每个用户一行显示所有标记。以下是我使用的表格结构

--
-- Table structure for table `Mark`
--

CREATE TABLE IF NOT EXISTS `Mark` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `studentID` int(11) NOT NULL,
  `subjectID` int(11) NOT NULL,
  `mark` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

--
-- Table structure for table `Student`
--

CREATE TABLE IF NOT EXISTS `Student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `classID` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

--
-- Table structure for table `Subject`
--

CREATE TABLE IF NOT EXISTS `Subject` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
谢谢是预付款。

试试这个

如果有更多的主题,只需添加更多带有不同主题的
GROUP\u CONCAT
行即可

下面是一个使用存储过程并使用游标动态构建查询的示例


此代码结构可从

中找到。至少在不动态生成SQL的情况下,您不能拥有动态列。您可以按照这个答案在存储过程中构建SQL


或者,在应用程序代码中执行此操作可能更简单,方法是在一个查询中选择不同的主题,并使用该结果集来构建检索所需结果集的SQL。至少通过应用程序代码中的逻辑,您对结果集中将看到多少列有了一些了解。

根据您所需的输出,我假设每个
studentID
有两行,并且每两行都有subjectID 1或2

你能试试这个吗

使用JOIN

SELECT t1.studentID, t1.mark AS subject_1, t2.mark AS subject_2
FROM
(
    SELECT `marks`.`studentID` , `marks`.mark
    FROM `Mark` as `marks`
    LEFT OUTER JOIN `Student` AS `students`
        ON ( `students`.`id` = `marks`.`studentID` AND subjectID = 1)
    WHERE `students`.`classID` =1
) t1 INNER JOIN 
(

    SELECT `marks`.`studentID` , `marks`.mark
    FROM `Mark` as `marks`
    LEFT OUTER JOIN `Student` AS `students`
        ON ( `students`.`id` = `marks`.`studentID` AND subjectID = 2)
    WHERE `students`.`classID` =1
) t2 ON t1.studentID = t2.studentID;
SELECT `marks`.`studentID`, 
    SUM(IF(subjectID = 1, mark, 0)) AS subject_1,
    SUM(IF(subjectID = 2, 0, mark)) AS subject_2
FROM `Mark` as `marks`
LEFT OUTER JOIN `Student` AS `students`
    ON ( `students`.`id` = `marks`.`studentID`)
WHERE `students`.`classID` =1
GROUP BY marks.studentID
使用交叉制表法

SELECT t1.studentID, t1.mark AS subject_1, t2.mark AS subject_2
FROM
(
    SELECT `marks`.`studentID` , `marks`.mark
    FROM `Mark` as `marks`
    LEFT OUTER JOIN `Student` AS `students`
        ON ( `students`.`id` = `marks`.`studentID` AND subjectID = 1)
    WHERE `students`.`classID` =1
) t1 INNER JOIN 
(

    SELECT `marks`.`studentID` , `marks`.mark
    FROM `Mark` as `marks`
    LEFT OUTER JOIN `Student` AS `students`
        ON ( `students`.`id` = `marks`.`studentID` AND subjectID = 2)
    WHERE `students`.`classID` =1
) t2 ON t1.studentID = t2.studentID;
SELECT `marks`.`studentID`, 
    SUM(IF(subjectID = 1, mark, 0)) AS subject_1,
    SUM(IF(subjectID = 2, 0, mark)) AS subject_2
FROM `Mark` as `marks`
LEFT OUTER JOIN `Student` AS `students`
    ON ( `students`.`id` = `marks`.`studentID`)
WHERE `students`.`classID` =1
GROUP BY marks.studentID

JOIN
CROSS tablation
是将垂直结果转换为水平结果的一般形式(以我有限的知识)

动态执行此操作是正确的,您必须编写一些存储过程,根据返回的subjectId数量动态构建sql。