【问题标题】:SQL - Window Count with resetSQL - 带重置的窗口计数
【发布时间】:2018-10-18 13:20:09
【问题描述】:

我正在使用 sql 并尝试实现以下结果 (running_count)。

我试过窗口函数计数,但我不知道如何实现我的计数器的重置。

select *,
     count(1) over 
(partition by ID, DATE order by DATE rows unbounded preceding) -1 as "run_count"  from table

我的(结果)应该是这样的。计数应在几天之间重置,但在 A 之间出现 B 时。

ID Date   Flag Running_Count
1  10/10   A   1 
**2  10/10   B   0** -> reset
**3  10/10   B   0** -> reset
4  10/10   A   1
5  10/10   A   2
6  10/10   A   3

1  11/10   B   0
2  11/10   B   0
3  11/10   A   1
4  11/10   A   2
5  11/10   A   3
6  11/10   A   4
**7  11/10   B   0** -> reset
8  11/10   A   1

【问题讨论】:

  • 请解释您的计数逻辑并用您正在使用的数据库标记问题。
  • 我已经做到了。谢谢

标签: sql function count sap hana


【解决方案1】:

您似乎想计算用“B”分隔的“A”,从每一天重新开始。

如果是这样,您可以将组定义为每个值之前的“B”数,然后进行一些计算:

select t.*,
       (case when flag = 'A' then row_number() over (partition by date, grp, flag order by id)
             else 0
        end) as running_count
from (select t.*, sum(case when flag = 'B' then 1 else 0 end) over (partition by date order by id) as grp
      from t
     ) t;

Here 是一个 rextester(使用 Postgres)。

【讨论】:

  • 嗨。谢谢,但你不是 100% 正确的。是的,我想计算每天分开的 A 和 B,但是当 B 在 A 之间时,
  • @user3733265 。 . .这就是它的作用。
  • @user3733265 。 . .我看到。 flag 需要在 partition by 子句中。我添加了一个rextester。它适用于 Postgres,但它的工作方式应该完全相同。
【解决方案2】:

请您尝试以下 SQLScript 选择语句

它可能会更容易解决。我使用子选择逐步显示解决方案。

最里面的 SELECT 使用SQL Lag() function检查是否有从另一个值到“A”的变化

下面的 SubSelect 使用 SUM() 聚合函数和无限的前置选项执行 SQL running-sum 解决方案

最外层的 SELECT 使用 Row_Number() 函数来创建所需的计数值。

select
    id,
    date,
    flag,
    case when flag = 'A' then
    row_number() over (partition by date, groupid order by id) 
    else 0
    end as rn
from (
    select
        id,
        date,
        flag,
        sum(is_change) over (partition by date order by id rows unbounded preceding) groupid -- running sum
    from (
        select
            id,
            date,
            flag,
            case 
                when 
                    flag = 'A' and 
                    (
                        (lag(flag, 1) over (partition by date order by id)) is null or
                        (lag(flag, 1) over (partition by date order by id)) = 'B'
                    ) -- check prev
                then 1
                else 0
            end as is_change
        from TblTest
    ) tbl
) t
order by date, id

希望对你有用,可以在你的开发中使用

【讨论】:

    【解决方案3】:

    您可以根据 B 标志出现的次数定义分组,然后使用 Row_number 为每个组的行编号:

    SELECT
        ID,
        date,
        flag,
        CASE WHEN flag = 'B' THEN 0 ELSE ROW_NUMBER() OVER (PARTITION BY date, B_COUNT ORDER BY ID) END AS "RUNNING_COUNT"
    FROM
        (
            SELECT
                TA.ID,
                TA.date,
                TA.flag,
                CASE WHEN SUM(TB.COUNT) IS NULL AND flag = 'A' THEN 0 ELSE SUM(TB.COUNT) END AS B_COUNT
            FROM
                table TA
                LEFT JOIN 
                            (
                                SELECT
                                    ID, date, 1 AS "COUNT"
                                FROM
                                    table
                                WHERE 
                                    flag = 'B'                  
                            )   TB ON TA.date = TB.date AND TA.ID > TB.ID AND TA.flag = 'A'
            GROUP BY
                TA.ID,
                TA.date,
                TA.flag
        )
    ORDER BY 
        date, ID, flag;
    

    它会给你预期的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 2021-06-26
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      • 2017-08-14
      相关资源
      最近更新 更多