Mysql 计算特定范围内行的百分比

Mysql 计算特定范围内行的百分比,mysql,sql,Mysql,Sql,我有一个学生名字和分数的列表存储在下面的表格中 CREATE TABLE StudentsList(StudentId INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(50), Marks INT); INSERT INTO StudentsList(Name, Marks) VALUES('Stud

我有一个学生名字和分数的列表存储在下面的表格中

CREATE TABLE StudentsList(StudentId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
                              Name  VARCHAR(50),
                              Marks INT);


INSERT INTO StudentsList(Name, Marks)
      VALUES('Student A', 20),
            ('Student B', 45),
            ('Student C', 90),
            ('Student D', 81),
            ('Student E', 50),
            ('Student F', 10),
            ('Student G', 85),
            ('Student H', 41),
            ('Student I', 66),
            ('Student J', 65),
            ('Student K', 05),
            ('Student L', 20),
            ('Student M', 19),
            ('Student N', 80),
            ('Student O', 90),
            ('Student P', 91),
            ('Student Q', 10),
            ('Student R', 29);
我想根据分数范围和学生占总人数的百分比对学生人数进行分组

    MarkRange   NoOfStudents  Percentage
      0 - 20       4             22.22
     20 - 50       5             27.77  
     50 - 70       3             16.66 
     70 - 90       3             16.66  
     90            3             16.66 
我尝试了下面的查询,并为0-20之间的学生带来了结果

SELECT COUNT(*) , COUNT(*)/(T.total)* 100
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks < 20
如何通过使用单一查询来实现此目的

请尝试以下方法:

SELECT COUNT(*) as 'number of students', COUNT(*)/(T.total)* 100 as 'Percentage', '0 - 20' AS 'Range' 
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks < 20
UNION
SELECT COUNT(*) , COUNT(*)/(T.total)* 100  as 'Percentage', '20 - 50' AS 'Range'
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks >= 20 and Marks < 50
UNION
SELECT COUNT(*) , COUNT(*)/(T.total)* 100 as 'Percentage', '50 - 70' AS 'Range'
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks >= 70 and Marks < 90
UNION
SELECT COUNT(*) , COUNT(*)/(T.total)* 100 as 'Percentage', '70 - 90' AS 'Range'
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks >= 70 and Marks < 90
UNION
SELECT COUNT(*) , COUNT(*)/(T.total)* 100 as 'Percentage', 'Above 90' AS 'Range'
  FROM StudentsList,
       (SELECT COUNT(*) AS total 
          FROM StudentsList) AS T 
         WHERE Marks >= 0 and  Marks >= 90 
order by 3
你可以看到它是如何运行的

我用Union找到了答案

如果有其他解决方案,请建议我尝试以下方法:

SELECT CONCAT(A.minRange, ' - ', A.maxRange) MarkRange, COUNT(sl.Name) NoOfStudents, 
    (SELECT COUNT(sl.Name) / COUNT(*) * 100 FROM StudentsList) Percentage
FROM studentslist sl 
INNER JOIN (SELECT 1 id, 0 minRange, 20 maxRange 
    UNION 
    SELECT 2 id, 20 minRange, 50 maxRange 
    UNION 
    SELECT 3 id, 50 minRange, 70 maxRange 
    UNION 
    SELECT 4 id, 70 minRange, 90 maxRange 
    UNION 
    SELECT 5 id, 90 minRange, 100 maxRange 
    ) AS A ON sl.Marks >= A.minRange AND sl.Marks < A.maxRange 
GROUP BY A.id;

看,有三个16.66学生组,所以根据你的查询,它将显示单个。我在上面发布了相同的东西。请检查它。+1这是一个很好的答案,但你的代码没有在sqlfiddler中编译,但如果您想修复它,只需使用as“Range”更改as Range的每一次出现,请参阅@saharsh Shah-感谢回复其工作GR8,您可以用另一种方式来完成此操作,即为表中的百分比范围创建一个表,并直接连接该表。您可以找到一种更快、更优化的查询方式
    SELECT COUNT(*) , COUNT(*)/(T.total)* 100, '0 - 20' AS Range
      FROM StudentsList,
           (SELECT COUNT(*) AS total 
              FROM StudentsList) AS T 
             WHERE Marks >= 0 and  Marks < 20
    UNION 
    SELECT COUNT(*) , COUNT(*)/(T.total)* 100, '20 - 50' AS Range
      FROM StudentsList,
           (SELECT COUNT(*) AS total 
              FROM StudentsList) AS T 
             WHERE Marks >= 20 and  Marks < 50
    UNION 
    SELECT COUNT(*) , COUNT(*)/(T.total)* 100, '50 - 70' AS Range
      FROM StudentsList,
           (SELECT COUNT(*) AS total 
              FROM StudentsList) AS T 
             WHERE Marks >= 50 and  Marks < 70
    UNION 
    SELECT COUNT(*) , COUNT(*)/(T.total)* 100, '70 - 90' AS Range
      FROM StudentsList,
           (SELECT COUNT(*) AS total 
              FROM StudentsList) AS T 
             WHERE Marks >= 70 and  Marks < 90
   UNION 
   SELECT COUNT(*) , COUNT(*)/(T.total)* 100, '90 Above' AS Range
     FROM StudentsList,
          (SELECT COUNT(*) AS total 
             FROM StudentsList) AS T 
            WHERE Marks >= 90
SELECT CONCAT(A.minRange, ' - ', A.maxRange) MarkRange, COUNT(sl.Name) NoOfStudents, 
    (SELECT COUNT(sl.Name) / COUNT(*) * 100 FROM StudentsList) Percentage
FROM studentslist sl 
INNER JOIN (SELECT 1 id, 0 minRange, 20 maxRange 
    UNION 
    SELECT 2 id, 20 minRange, 50 maxRange 
    UNION 
    SELECT 3 id, 50 minRange, 70 maxRange 
    UNION 
    SELECT 4 id, 70 minRange, 90 maxRange 
    UNION 
    SELECT 5 id, 90 minRange, 100 maxRange 
    ) AS A ON sl.Marks >= A.minRange AND sl.Marks < A.maxRange 
GROUP BY A.id;