Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
368 views
in Technique[技术] by (71.8m points)

matrix - MySQL query to create a pivot table by joining 4 different table

I have 4 mySQL tables namely Exams, Marks, Student and Subject. Sql with data is provided below. I need the output like below screenshot.

enter image description here

Marks is calculated from all Marks added together for the particular subject and student pair with their proper Weightage in Percentage (Exams with 0 Weightage are ignored)

I tried using the below query but the result didn't gave the cumulative marks so need help.

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
               CONCAT('MAX(IF(sj.SubjectId = ''', SubjectId,''', pa.Marks, NULL)) AS ',SubjectId)
              ) INTO @sql
FROM Subject;

SET @sql = CONCAT('SELECT s.ID, s.StudentID, s.FirstName, s.LastName, ', @sql, ' 
                  FROM Student s
                  JOIN Marks AS pa 
                  ON pa.StudentID = s.StudentID AND pa.OrganizationId = s.OrganizationId 
                  JOIN Exams p
                  ON p.ExamId = pa.ExamId AND p.OrganizationId = pa.OrganizationId
                  JOIN Subject sj
                  ON p.SubjectId = sj.SubjectId AND pa.OrganizationId = sj.OrganizationId
                  WHERE p.Weightage > 0
                  GROUP BY s.ID');

PREPARE stmt FROM @sql;
EXECUTE stmt;

Please help. FIDDLE LINK


CREATE TABLE `Exams` (
  `ID` int(6) NOT NULL,
  `ExamId` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `Date` datetime(6) DEFAULT NULL,
  `TotalMarks` int(6) NOT NULL,
  `SubjectId` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
  `Weightage` int(6) NOT NULL DEFAULT '0',
  `OrganizationId` int(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `Exams`
--

INSERT INTO `Exams` (`ID`, `ExamId`, `Name`, `Date`, `TotalMarks`, `SubjectId`, `Weightage`, `OrganizationId`) VALUES
(8, 'EX_0001', 'Test 1', '2020-05-30 17:15:38.000000', 50, 'SUB_0002', 0, 116),
(9, 'EX_0002', 'Test 2', '2020-05-17 17:15:19.000000', 30, 'SUB_0001', 0, 116),
(10, 'EX_0003', 'Test 3', '2020-05-17 17:15:51.000000', 30, 'SUB_0003', 10, 116),
(11, 'EX_0004', 'Test 45', '2020-05-19 15:15:08.000000', 30, 'SUB_0001', 0, 116),
(12, 'EX_0005', 'Final Exam', '2020-05-20 15:30:53.000000', 100, 'SUB_0001', 80, 116),
(13, 'EX_0006', 'Terminal 3', '2020-05-20 15:30:03.000000', 50, 'SUB_0001', 10, 116);

-- --------------------------------------------------------

--
-- Table structure for table `Marks`
--

CREATE TABLE `Marks` (
  `ID` int(11) NOT NULL,
  `StudentId` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
  `ExamId` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
  `Marks` int(6) NOT NULL,
  `OrganizationId` int(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `Marks`
--

INSERT INTO `Marks` (`ID`, `StudentId`, `ExamId`, `Marks`, `OrganizationId`) VALUES
(14, 'S_100000001', 'EX_0004', 30, 116),
(15, 'S_100000001', 'EX_0003', 25, 116),
(16, 'S_100000001', 'EX_0002', 77, 116),
(17, 'S_100000003', 'EX_0003', 15, 116),
(18, 'S_100000003', 'EX_0004', 12, 116),
(19, 'S_100000003', 'EX_0001', 12, 116),
(20, 'S_100000002', 'EX_0004', 20, 116),
(21, 'S_100000002', 'EX_0003', 21, 116),
(22, 'S_100000001', 'EX_0005', 80, 116),
(23, 'S_100000002', 'EX_0005', 90, 116);

-- --------------------------------------------------------

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

CREATE TABLE `Student` (
  `ID` int(6) NOT NULL,
  `GradeId` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
  `StudentID` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `OrganizationId` int(6) DEFAULT NULL,
  `FirstName` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `LastName` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `FatherFirstName` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `FatherLastName` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `DateOfBirth` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `PlaceOfBirth` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `Sex` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `Carnet` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `MobilePhone` bigint(8) DEFAULT NULL,
  `Address` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
  `MotherFirstName` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `MotherLastName` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `FatherMobilePhone` bigint(8) DEFAULT NULL,
  `MotherMobilePhone` bigint(8) DEFAULT NULL,
  `FatherProfession` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `MotherProfession` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `Observations` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `Student`
--

INSERT INTO `Student` (`ID`, `GradeId`, `StudentID`, `OrganizationId`, `FirstName`, `LastName`, `FatherFirstName`, `FatherLastName`, `DateOfBirth`, `PlaceOfBirth`, `Sex`, `Carnet`, `MobilePhone`, `Address`, `MotherFirstName`, `MotherLastName`, `FatherMobilePhone`, `MotherMobilePhone`, `FatherProfession`, `MotherProfession`, `Observations`) VALUES
(21, 'G_016', 'S_100000001', 116, 'Student', 'One', '', '', '', '', 'male', NULL, 8178109047, '', '', '', 0, 0, NULL, NULL, NULL),
(22, 'G_016', 'S_100000002', 116, 'Student', 'two', '', '', '', '', 'female', NULL, 0, '', '', '', 0, 0, NULL, NULL, NULL),
(23, 'G_002', 'S_100000003', 116, 'Student3', 'three', NULL, NULL, NULL, NULL, 'male', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

-- --------------------------------------------------------

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

CREATE TABLE `Subject` (
  `ID` int(6) NOT NULL,
  `SubjectId` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `Name` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `Abbreviation` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `GradeId` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `OrganizationId` int(6) NOT NULL,
  `StaffId` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `Subject`
--

INSERT INTO `Subject` (`ID`, `SubjectId`, `Name`, `Abbreviation`, `GradeId`, `OrganizationId`, `StaffId`) VALUES
(12, 'SUB_0001', 'English 1A', 'Eng_1A', 'G_016', 116, 'E_100000030'),
(13, 'SUB_0002', 'English 1B', 'Eng_1B', 'G_002', 116, '0'),
(14, 'SUB_0003', 'Science 1A', 'Sci_1A', 'G_016', 116, 'E_100000030');


See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ok with your last comment, your query would look like this

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
               CONCAT('SUM(IF(sj.SubjectId = ''', SubjectId,''', ROUND((pa.`Marks` * p.`Weightage` / 100),1),0)) AS ',SubjectId)
              ) INTO @sql
FROM Subject;

SET @sql = CONCAT('SELECT s.ID, s.StudentID, s.FirstName, s.LastName, ', @sql, ' 
                  FROM Student s
                  JOIN Marks AS pa 
                  ON pa.StudentID = s.StudentID AND pa.OrganizationId = s.OrganizationId 
                  JOIN Exams p
                  ON p.ExamId = pa.ExamId AND p.OrganizationId = pa.OrganizationId
                  JOIN Subject sj
                  ON p.SubjectId = sj.SubjectId AND pa.OrganizationId = sj.OrganizationId
                  WHERE p.Weightage > 0
                 GROUP BY s.ID
                 ORDER BY s.ID');
#SELECT @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;


ID | StudentID   | FirstName | LastName | SUB_0001 | SUB_0002 | SUB_0003
-: | :---------- | :-------- | :------- | -------: | -------: | -------:
21 | S_100000001 | Student   | One      |     71.7 |      0.0 |      2.5
22 | S_100000002 | Student   | two      |     72.0 |      0.0 |      2.1
23 | S_100000003 | Student3  | three    |      0.0 |      1.2 |      1.5

db<>fiddle here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...