【问题标题】:MySQL Merge Row Values into single RowMySQL将行值合并到单行中
【发布时间】:2012-01-09 15:22:05
【问题描述】:

我需要为一个表创建一个选择查询,该表合并“数字”列上每个组的行,以获得包含所有可用但最新(按 ID)列的单行。

我的意思是,我需要这样一张桌子:

ID | Number |   Date 1   |   Date 2   |   Date 3   |
----------------------------------------------------
1  |   1    | 2011-10-01 |    NULL    |    NULL    |
2  |   1    |    NULL    | 2011-10-25 |    NULL    |
3  |   1    |    NULL    |    NULL    | 2011-11-13 |
4  |   1    | 2011-10-03 |    NULL    | 2011-11-10 |
5  |   2    |    NULL    |    NULL    | 2012-01-01 |
6  |   2    | 2012-03-11 |    NULL    |    NULL    |

并返回此(ID 列与上述 ID 列无关):

ID | Number |   Date 1   |   Date 2   |   Date 3   |
----------------------------------------------------
1  |    1   | 2011-10-03 | 2011-10-25 | 2011-11-10 |
2  |    2   | 2012-03-11 |    NULL    | 2012-01-01 |

因此,对于每个 Group By 'Number' 列中的所有行,我需要该组中所有行的所有可用列值,但只需要每列的最新值。最新的由列中存在值的“ID”的最大值确定。 (如果组中的任何行上不存在列中的值,则使用 Null 值)。

谢谢

【问题讨论】:

    标签: mysql sql merge greatest-n-per-group


    【解决方案1】:

    您可以使用子查询来选择不同的数字。然后对于每个数字,您可以在另一个子查询中查找各个列。子查询将查找具有最高 ID 且该特定列不为空的行。

    select  yt.Number
    ,       (
            select  top 1 [Date 1]
            from    YourTable d1
            where   d1.Number = yt.Number
                    and d1.[Date 1] is not null
            order by
                    d1.ID desc
            ) as [Date 1]
    ,       (
            select  top 1 [Date 2]
            from    YourTable d2
            where   d2.Number = yt.Number
                    and d2.[Date 2] is not null
            order by
                    d1.ID desc
            ) as [Date 2]
    ,       ...
    from    (
            select  distinct Number
            from    YourTable
            ) as yt
    

    【讨论】:

    • 哇,好快!!!我对大量子查询的担忧是,我将使用的实际表有超过 200,000 行,每组最多 20-30 行。
    • 可以进一步优化,但先试试? 200k 行对于 SQL Server 来说并不多
    【解决方案2】:

    这加深了您的数据,您也可以使用聚合函数。*

    如果您的数据在 other 行中始终包含空值,则聚合函数将忽略它们。这意味着您可以使用 GROUP BY 来获取单行。

    SELECT ID, Number, MAX(Date1), MAX(Date2), MAX(Date3)
    FROM MyTable
    GROUP BY ID, Number
    

    *注意:这只有在你知道你总是想要当然值的最大值(或最小值)时才有效。在您的问题中,您声明您想要 ID 最高的那个,所以我的解决方案可能不起作用。

    【讨论】:

      【解决方案3】:

      您要查找的“ID”编号似乎是简单的顺序,表示结果集的最终“行”编号(正如您所指出的与原始 ID 列无关)。所以,考虑到 Cylindric 之前的回答,稍微扩展一下......

      select 
            @FinalRow := @FinalRow +1 as ID,
            PreQuery.*
         from
            ( SELECT 
                    Number, 
                    MAX(Date1), 
                    MAX(Date2), 
                    MAX(Date3)
                 FROM 
                    MyTable
                 GROUP BY 
                    Number 
                 ORDER BY 
                    Number ) PreQuery,
            (select @FinalRow := 0 ) SQLVars   
      

      【讨论】:

        【解决方案4】:

        感谢大家的建议。不幸的是,我无法让任何当前的答案对我有用。 不幸的是,我不能依赖对日期使用聚合函数,因为它们可能不是最大值或最小值。 每个日期列使用子查询非常聪明,但我无法使查询运行得足够快以供我使用。 (它需要几乎立即运行,但尽管正确配置了索引,却花费了过多的时间。)

        我想出的解决方案是创建一个具有保存结果的结构的新表,然后使用多个触发器使该表保持最新。有问题的实际表会定期更新,表中的插入应该允许我使用触发器保持一个单独的表是最新的,从而给我我需要的东西。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-26
          • 2015-09-27
          • 1970-01-01
          • 2015-11-26
          • 1970-01-01
          相关资源
          最近更新 更多