SQL - Счетчик окон со сбросом - PullRequest
0 голосов
/ 18 октября 2018

Я использую sql и пытаюсь добиться следующих результатов (running_count).

Я попробовал подсчет оконных функций, но я не знаю, как добиться сброса моего счетчика.

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

Мой (результат) должен выглядеть следующим образом.Счетчик должен сбрасываться между днями, но также , когда B находится между A.

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

Ответы [ 3 ]

0 голосов
/ 19 октября 2018

Не могли бы вы, пожалуйста, попробовать следующий оператор SQLScript select

Возможно, что это может быть решено проще.Я использовал подвыборки, чтобы отобразить решение шаг за шагом.

Внутренний большинство SELECT проверяет, есть ли изменение с другого значения на 'A', используя SQL Lag () function

Следующий SubSelect выполняет решение SQL-счет , используя агрегатную функцию 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

Я надеюсь, что это полезно и может быть использовано в вашей разработке

enter image description here

0 голосов
/ 19 октября 2018

Вы можете определить группировку на основе количества вхождений флага 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;

Это даст ожидаемый результат.

0 голосов
/ 18 октября 2018

Вы, кажется, хотите посчитать буквы «A», разделенные буквой «B», начиная с каждого дня.

Если это так, вы можете определить группу как число «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;

Здесь - реекстер (использующий Postgres).

...