【问题标题】:T-SQL grouping data with conditionT-SQL 使用条件对数据进行分组
【发布时间】:2020-10-22 18:29:24
【问题描述】:

我有一些数据:

句号 | id_account |浮点值
24217 | 303003 | 0
24218 | 303003 | 0
24219 | 303003 | 1
24220 | 303003 | 1
24221 | 303003 | 0
24222 | 303003 | 0

我需要像这样对这些数据进行分组:

begin_period | end_period| id_account | float_value     
24217       | 24218     | 303003    |   0   
24219       | 24220     | 303003    |   1   
24221       | 24222     | 303003    |   0   

我通过分区和while循环尝试了row_number,但没有成功。

【问题讨论】:

    标签: sql sql-server select window-functions gaps-and-islands


    【解决方案1】:

    我将此理解为一个间隙和问题问题,您希望将“相邻”行组合在一起,即具有相同 float_value 的行,跨具有相同 id_accountparameter 的记录。

    在这里,我认为最简单的方法是使用行号之间的差异来计算每条记录属于哪个组:

    select
        min(period) begin_period,
        max(period) end_period,
        id_account,
        parameter,
        float_value
    from (
        select 
            t.*,
            row_number() over(partition by id_account, parameter order by period) rn1,
            row_number() over(partition by id_account, parameter, float_value order by period) rn2
        from mytable t
    ) t
    group by id_account, parameter, float_value, rn1 -rn2
    order by id_account, parameter, begin_period
    

    Demo on DB Fiddle

    开始周期 | end_period | id_account |参数 |浮点值 ------------: | ---------: | ---------: | :------------- | ----------: 24217 | 24218 | 303003 |帐户状态 | 0 24219 | 24220 | 303003 |帐户状态 | 1 24221 | 24222 | 303003 |帐户状态 | 0

    【讨论】:

      【解决方案2】:

      这是一个间隙和孤岛问题,一种方法是使用行数差异法:

      WITH cte AS (
          SELECT *, ROW_NUMBER() OVER (PARTITION BY ID_Account ORDER BY Period) rn1,
              ROW_NUMBER() OVER (PARTITION BY ID_Account, Float_Value ORDER BY Period) rn2
          FROM yourTable
      )
      
      SELECT
          MIN(Period) AS Begin_Period,
          MAX(Period) AS End_Period,
          ID_Account,
          MAX(Parameter) AS Parameter,   -- assuming Parameter just always has the same value
          Float_Value
      FROM cte
      GROUP BY
          ID_Account,
          Float_Value,
          rn1 - rn2
      ORDER BY
          MIN(Period);
      

      Demo

      【讨论】:

        【解决方案3】:

        您可以使用row_number,如下所示。这是demo

        with cte as
        (
          select
             *,
             rn - row_number() over(order by Float_Value, rn) as nrnk
          from
          (
            select
              *,
              row_number() over (order by Period) as rn
            from Table1
          ) subq
        )
        
        select
          min(Period) as Begin_Period,
          max(Period) as End_Period,
          ID_Account,
          Parameter,
          Float_Value
        from cte
        group by
          ID_Account,
          Parameter,
          Float_Value,
          nrnk
        

        输出:

         Begin_Period   End_Period     ID_Account     Parameter   Float_Value
        ---------------------------------------------------------------------
         24217            24218          303003    ACCOUNT_STATUS   0
         24221            24222          303003    ACCOUNT_STATUS   0
         24219            24220          303003    ACCOUNT_STATUS   1
        

        【讨论】:

          猜你喜欢
          • 2017-02-15
          • 1970-01-01
          • 2016-09-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多