我遇到了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
谢谢你的到来。
答案 0 :(得分:2)
您不能拥有动态列,至少不能动态生成SQL。您可以根据此答案在存储过程中构建SQL
MySQL pivot table query with dynamic columns
或者,通过在一个查询中选择不同的主题并使用该结果集构建检索您所追求的结果集的SQL,可以更简单地在应用程序代码中执行此操作。至少使用应用程序代码中的逻辑,您可以了解在结果集中将看到多少列。
答案 1 :(得分:0)
试试这个 sqlFiddle demo
SELECT `marks`.`studentID` ,
GROUP_CONCAT(if(`marks`.`subjectID`=1,`marks`.`mark`,NULL)) AS subject_1,
GROUP_CONCAT(if(`marks`.`subjectID`=2,`marks`.`mark`,NULL)) AS subject_2
FROM `Mark` `marks`
LEFT OUTER JOIN `Student` `students` ON ( `students`.`id` = `marks`.`studentID` )
WHERE (
`students`.`classID` =1
)
GROUP BY `marks`.`studentID`
如果有更多主题,只需添加更多具有不同GROUP_CONCAT
subjectID
行
下面是使用存储过程的示例,并使用游标动态构建查询 sqlFiddle
DROP PROCEDURE IF EXISTS getMarks//
CREATE PROCEDURE getMarks (IN INclassID INT)
BEGIN
-- First we declare all the variables we will need
DECLARE loopSubjectId INT;
DECLARE dynamicSql VARCHAR(5000);
DECLARE finalSql VARCHAR(5000);
-- flag which will be set to true, when cursor reaches end of table
DECLARE exit_loop BOOLEAN;
-- Declare the sql for the cursor
DECLARE example_cursor CURSOR FOR
SELECT DISTINCT subjectID
FROM Student s, Mark m
WHERE s.id = m.studentID
AND s.classID = INclassID;
-- Let mysql set exit_loop to true, if there are no more rows to iterate
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
SET dynamicSql = '';
SET finalSql = '';
-- open the cursor
OPEN example_cursor;
-- marks the beginning of the loop
example_loop: LOOP
-- read the name from next row into the variable l_name
FETCH example_cursor INTO loopSubjectId;
-- check if the exit_loop flag has been set by mysql,
-- if it has been set we close the cursor and exit
-- the loop
IF exit_loop THEN
CLOSE example_cursor;
LEAVE example_loop;
END IF;
SET DynamicSql = CONCAT(DynamicSql,',GROUP_CONCAT(if(marks.subjectID=',loopSubjectId,',marks.mark,NULL)) AS subject_',loopSubjectId);
END LOOP example_loop;
SET finalSql = CONCAT('SELECT students.name,marks.studentID',DynamicSql,
' FROM Mark marks
LEFT OUTER JOIN Student students ON (students.id = marks.studentID)
WHERE (students.classID=?)
GROUP BY marks.studentID');
-- now we run set some variables and run the dynamically built query
SET @finalSql = finalSql;
SET @INClassId = INClassID;
PREPARE stmt1 FROM @finalSql;
EXECUTE stmt1 USING @INclassID;
END//
此代码结构可从this example
找到答案 2 :(得分:0)
根据您所需的输出,我假设每个studentID
有2行,并且2行中的每一行都有subjectID 1或2。
你可以尝试一下吗?
使用加入
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;
使用CROSS TABULATION
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 TABULATION
是将垂直结果转换为水平结果的常规形式(我的知识有限)