【问题标题】:Grouping data issue分组数据问题
【发布时间】:2019-01-13 16:46:50
【问题描述】:

我创建了虚拟表来探索 SQL 中的分组概念。

我想对数据进行分组显示,

  1. 学生总分。
  2. 希望以逗号分隔的方式显示主题。

我的问题:为什么 SQL 不允许在 GROUP BY 子句中只保留 StudentID,当我们在 GROUP BY 子句中提到 ID、名称、.. 其他列时,它是允许的。

我收到此错误:

选择列表中的“SampleData.StudentName”列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

以及如何在 SQL 输出中以逗号分隔显示主题?

这是我写的 SQL:

SELECT
    StudentID, 
    StudentName,
    Standard,
    Subject,
    SUM(MarksObtained) 
FROM
    SampleData
GROUP BY
    StudentID, StudentName 
    --,Standard 
    --,Subject 
ORDER BY 
    StudentID

供参考的样本表:

StudentID StudentName Standard Subject MarksObtained 
-----------------------------------------------------
1         A           VI       Maths              59   
3         C           VII      English            62   
2         B           IX       Maths              75   
2         B           IX       English            81   
1         A           VI       Science            47   
1         A           VI       History            61   

预期输出:

StudentID StudentName Standard Subject                MarksObtained 
-------------------------------------------------------------------
1         A           VI       Maths,Science,History  167   
3         C           VII      English                62   
2         B           IX       Maths,English          156   

【问题讨论】:

  • 你在处理哪个 dbms ?
  • SQL 服务器。但是,我想要适用于所有服务器的通用查询。
  • 对于字符串 concat 你不能有一般查询。请检查我的答案
  • 感谢西蒙娜提供的信息。现在很清楚了。如果有任何与此相关的查询,将再次发布。任何想法,如何在 SQL Server 2012 中实现这一点?
  • 感谢@GMB 提供信息。

标签: sql group-by


【解决方案1】:

对于您的第一个问题:

当您发出 sum、count、max、min、avg 等聚合时,您需要对其他非聚合列进行分组。聚合是针对分组列完成的。

你的查询在英文中是什么意思,

从 SampleData 中获取关于 StudentID、StudentName、Standard、Subject 的 MarksObtained 总和

第二个问题:

我们需要知道您正在使用哪个 DBMS。每个 DBMS 系统都有自己的方法

  • Oracle 有LISTAGG(column, ',')
  • MySQL 有GROUP_CONCAT(column, ',')
  • SQL Server 有STR_AGG(column, ',')
  • PostgreSQL 有string_agg(column, ',')

【讨论】:

    【解决方案2】:

    最好将SELECTed 的所有非聚合字段明确放入GROUP BY 子句中。一些 RDBMS 对此很严格(例如 Oracle),而另一些则可能比较宽松(例如 MySQL 的 sql 模式 ONLY_FULL_GROUP_BY 已禁用)。

    要将Subject 连接到单个字段中,您需要一个聚合函数。并非所有 RDBMS 都有相同的标准。他们通常接受ORDER BY 选项。

    使用 SQL Server 2017 或更高版本:STR_AGG

    SELECT
         StudentID 
        ,StudentName 
        ,Standard 
        ,STR_AGG(Subject, ',') WITHIN GROUP ( ORDER BY StudentID)
        ,SUM(MarksObtained) 
    FROM
        SampleData
    GROUP BY
         StudentID 
        ,StudentName 
        ,Standard 
    ORDER BY 
        StudentID
    

    使用 MySQL:GROUP_CONCAT

    SELECT
         StudentID 
        ,StudentName 
        ,Standard 
        ,GROUP_CONCAT(Subject ORDER BY StudentID SEPARATOR ', ')
        ,SUM(MarksObtained) 
    FROM
        SampleData
    GROUP BY
         StudentID 
        ,StudentName 
        ,Standard 
    ORDER BY 
        StudentID
    

    使用 Oracle 11g 或更高版本:LISTAGG

    SELECT
         StudentID 
        ,StudentName 
        ,Standard 
        ,LISTAGG(Subject, ',') WITHIN GROUP ( ORDER BY StudentID)
        ,SUM(MarksObtained) 
    FROM
        SampleData
    GROUP BY
         StudentID 
        ,StudentName 
        ,Standard 
    ORDER BY 
        StudentID
    

    【讨论】:

    • 平心而论,如果sql模式包含ONLY_FULL_GROUP_BY,MySQL对分组规则并不松懈,从MySQL 5.7.5 (2014-09-25)开始默认启用。
    • 因此,无论 DBMS 是否允许,在 GROUP BY 子句中包含所有非聚合字段始终是一个好习惯。
    • @BillKarwin :是的,你是对的,从那时起 MySQL 就不那么松懈了,我更新了我的答案来提及它。
    • @AnujThite :是的,完全正确。
    • 谢谢大家。我将在进行 SQL 开发时将此作为经验法则。..
    猜你喜欢
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多