2013-12-14 36 views
3

我遇到了MySQL問題。我想擁有基於行的動態列。這裏是沒有的科目可以非常依賴於主題表格中的enteries細節將行轉換爲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 

感謝提前。

回答

2

您不能擁有動態列,至少不能動態生成SQL。您可以在存儲過程中生成SQL按照這個答案

MySQL pivot table query with dynamic columns

另外,它可以通過在一個查詢選擇不同的主題,並使用該結果集來構建更簡單地做到這一點在你的應用程序代碼用於檢索您之後的結果集的SQL。至少使用應用程序代碼中的邏輯,您可以瞭解在結果集中您將看到多少列。

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` 

是否有更多的受試者只使用一個例子的存儲過程和動態地建立查詢使用遊標 具有不同subjectID

下面

添加更多GROUP_CONCATsqlFiddle

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

+0

一點也沒有實際上並沒有動態添加列儘管... – abasterfield

+0

你是對的動態做到這一點,你將不得不編寫一些存儲過程,以根據返回的subjectId的數量動態構建sql。 –

0

根據您所需的輸出,我假設有2行每個studentID和各2行已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 

JOINCROSS TABULATION是一般形式垂直結果轉換爲橫向(與我的受限知識)