【问题标题】:MySQL - show field value only in first instance of each grouped value?MySQL - 仅在每个分组值的第一个实例中显示字段值?
【发布时间】:2010-10-29 07:06:48
【问题描述】:

我认为这是不可能的,但我希望得到证明。

我写了一个简单的报表查看类来输出各种数据库查询的结果。为了改进显示,当我有一个包含分组数据的报告时,我想只在每个唯一值的第一行显示字段值 - 我想在查询级别执行此操作,或者它会需要在我的类中添加额外的逻辑来确定这些特殊值。

用一个简单的例子来说明我的要求可能会有所帮助。想象一下这个数据集:

Year    Quarter    Total
2008    Q1         20
2008    Q2         25
2008    Q3         35
2008    Q4         40
2009    Q1         15
2009    Q2         20
2009    Q3         30
2009    Q4         35

如果可能,我希望数据集返回为:

Year    Quarter    Total
2008    Q1         20
        Q2         25
        Q3         35
        Q4         40
2009    Q1         15
        Q2         20
        Q3         30
        Q4         35

有没有办法在 MySQL 中以编程方式执行此操作?

【问题讨论】:

    标签: sql mysql dataset group-by grouping


    【解决方案1】:
    SELECT  CASE WHEN @r = year THEN NULL ELSE year END AS year,
            quarter,
            total,
            @r := year
    FROM    (
            SELECT  @r := 0
            ) vars,
            mytable
    ORDER BY
            year
    

    @r 这里是一个会话变量。您可以在MySQL 中使用它们,就像在任何程序语言中使用任何变量一样。

    首先,它在子查询中被初始化为零。

    其次,在SELECT 子句中检查。如果@r的当前值不等于year,则输出year,否则输出NULL

    第三,更新为year的当前值。

    【讨论】:

    • +1 虽然这在报告客户端中做得更好:P
    • +1 是一个可行的解决方案,但需要相当多的精力来维护 - 比处理我课堂上的功能更重要。我想我要做的是将一个值附加到列名,以标记我的类以某种方式显示数据。例如,“Year__FirstGroup”。
    • @BrynJ:正如@Andomar 所说,这当然在客户端上做得更好,但我真的不明白你所说的“努力维护”是什么意思。这个查询一旦编写就不会中断,这里没有什么需要维护的:)
    • @Quassnoi - 也许我应该说努力制作,只是在接下来的几周内我会有很多报告要写。
    • @BrynJ:啊,好的。不过,一旦您习惯了 Session 变量,它们并没有那么难。
    【解决方案2】:

    您为什么要这样做? Year 列为空或 null 的现有记录怎么办?

    美化输出属于报表逻辑。在伪代码中它会是某事。喜欢:

    var lastYear = 0
    foreach (record in records)
    {
       if (record.Year == lastYear)
       {
         print "   "
       }
       else
       {
         print record.Year
         lastYear = record.Year
       }
    
       // print the other columns
     }
    

    【讨论】:

    • 是的,我明白你在说什么 - 我只是在寻找最简单的方法来实现/维护。如果在 MySql 中有这样的解决方案,也许是以 GROUP_CONCAT 等函数的形式,那么这将是一个简单、可维护的解决方案。
    • 我想我要做的是将某个字符串附加到我想要像这样分组的列名(在查询级别)。例如:SELECT YEAR(date) AS 'Year__FirstGroup', MONTH(date) AS Month, SUM(whatever) AS Total FROM mytable GROUP BY Year, Month
    【解决方案3】:

    不是你要的答案,而是……

    一开始,在 MySQL 中做这件事听起来很可疑。仅查看原始数据行,2008 年和 2009 年第二季度的数据行似乎没有多大意义。这个问题是表象的,而不是获取数据的问题。听起来更像是要写入查看类的内容 - 例如,当传递某个参数时,它会知道不要重复“2008”之类的内容。

    这还可以提高代码的可重用性:当您希望以不同的方式呈现数据时(比如按季度而不是按年份),与其重写查询,不如只更改查看类的一个参数,以便具有不同 order 子句的相同查询可以输出:

    Quarter   Year   Total
    Q1        2008   20
              2009   15
    Q2        2008   25
              2009   20
    ...
    

    【讨论】:

    • 我很欣赏从数据的角度来看它没有多大意义 - 我只是希望有一种简单的方法可以在 mysql 中使用内置函数执行此操作,就像你一样有 GROUP_CONCAT 等。
    【解决方案4】:

    它不完全符合您的要求,但我宁愿旋转我的表格。它允许直观地比较 2 年的数据,因为每列有四分之一:

    SELECT Year, 
           SUM(IF(Quarter="Q1", Rev, 0)) AS Q1,
           SUM(IF(Quarter="Q2", Rev, 0)) AS Q2, 
           SUM(IF(Quarter="Q3", Rev, 0)) AS Q3, 
           SUM(IF(Quarter="Q4", Rev, 0)) AS Q4 
    FROM t1 GROUP BY 1
    ORDER BY 1
    

    然后你有:

    YEAR Q1   Q2   Q3   Q4
    2008
    2009 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多