Рассчитать количество на основе нескольких групп из 7 числового диапазона в Oracle - PullRequest
0 голосов
/ 31 января 2020

Может кто-нибудь помочь мне, я застрял здесь.

Учитывая

AMOUNT  CUSTOMER_NUMBER GROUPID SEQF
1000+   5555            51      2       
1000+   5555            52      3
1000+   5555            55      4   
1000+   5555            56      4   
1000+   5555            57      4       
1000+   5555            58      2   
1000+   5555            59      4   
1000+   5555            61      2
2000+   6666            55      2
.
.   
.
.

Учитывая столбцы AMOUNT и CUSTOMER_NUMBER, здесь создается группа в пределах 7 номеров GROUPID

Например, 1-я группа для 5555 CUSTOMER_NUMBER -> (от 51 до 57 ID группы), 2-я группа для 5555 CUSTOMER_NUMBER (от 58 до 61 ID группы), 3-я группа для 6666 CUSTOMER_NUMBER (55 GROUP) ID)

Необходимо:

IF SEQF> = 2 в 1-й группе в любом из GROUPID от 51 до 57, затем рассмотрите COUNT (SEQF) = 1

ЕСЛИ SEQF> = 2 во 2-й группе в любом из GROUPID от 58 до 61, тогда рассмотрите COUNT (SEQF) = 1

, итого здесь

AMOUNT  CUSTOMER_NUMBER COUNT(SEQF)
1000+       5555                2

IF SEQF> = 2 в 3-й группе в любом из GROUPID из 55, затем рассмотрим COUNT (SEQF) = 1

AMOUNT  CUSTOMER_NUMBER COUNT(SEQF)
2000+       6666                1

Желаемый выход

AMOUNT  CUSTOMER_NUMBER COUNT(SEQF)
1000+       5555                2
2000+       6666                1

Ответы [ 3 ]

0 голосов
/ 31 января 2020

Сначала нужно найти 7 диапазонов GROUPID, например, использовать этот иерархический запрос:

with ranges(amt, cn, g1, g2, mxg) as (
  select amount, customer_number, min(groupid), min(groupid) + 6, max(groupid)
    from data group by amount, customer_number union all
  select amt, cn, g1 + 7, g2 + 7, mxg from ranges where g1 + 7 <= mxg)
select amt, cn, g1, g2, mxg from ranges

, который дает нам нижний и верхний предел каждого диапазона (G1, G2):

AMT           CN         G1         G2 
----- ---------- ---------- ---------- 
1000+       5555         51         57 
1000+       5555         58         64 
2000+       6666         55         61 

Теперь мы можем объединить эти диапазоны с вашими данными, считать условно и рассчитывать суммы:

with ranges(amt, cn, g1, g2, mxg) as (
    select amount, customer_number, min(groupid), min(groupid) + 6, max(groupid)
      from data group by amount, customer_number union all
    select amt, cn, g1 + 7, g2 + 7, mxg from ranges where g1 + 7 <= mxg)
select amt, cn, sum(cs) cnt
  from (
    select amt, cn, g1, g2, case when max(seqf) >= 2 then 1 end cs
      from ranges
      join data on amt = amount and cn = customer_number 
               and groupid between g1 and g2
      group by amt, cn, g1, g2)
  group by amt, cn

Демо-версия dbfiddle

Я использовал max(seqf), потому что ваши слова IF SEQF> = 2 в 1-й группе в любом из GROUPID предполагают это. Если вы хотите получить первое значение в этой группе, например, используйте min ... keep dense rank first.


Вы также можете вычесть groupid и минимальный groupid для каждого (сумма, customer_number), разделить на 7, использовать floor, и это будет создавать группы, это будет быстрее:

select amount, customer_number, sum(seqf)
  from (
    select amount, customer_number, case when max(seqf) >= 2 then 1 end seqf
      from (
        select data.*, 
               floor((groupid - min(groupid) over (partition by amount, customer_number))/7) gid
          from data)
      group by amount, customer_number, gid)
  group by amount, customer_number
0 голосов
/ 31 января 2020

Ни один из других ответов не решает проблему, в которой есть разрывы между группами (они просто предполагают, что группы являются смежными). Это пропустит пропуски и поместит groupid в диапазоны 7.

Oracle Настройка :

create table data(amount, customer_number, groupid, seqf) as (
    select '1000+', 5555, 51, 2 from dual union all
    select '1000+', 5555, 52, 3 from dual union all
    select '1000+', 5555, 55, 4 from dual union all
    select '1000+', 5555, 56, 4 from dual union all
    select '1000+', 5555, 57, 4 from dual union all
    select '1000+', 5555, 60, 2 from dual union all
    select '1000+', 5555, 61, 4 from dual union all
    select '1000+', 5555, 65, 2 from dual union all
    select '1000+', 5555, 69, 2 from dual union all
    select '2000+', 6666, 55, 2 from dual );

Запрос 1 :

Находит группы:

SELECT amount,
       customer_number,
       groupid,
       groupid + 6 AS max_groupid
FROM   (
  SELECT d.*,
         MIN( groupid )
           OVER ( PARTITION BY amount, customer_number )
           AS min_groupid,
         MIN( groupid )
           OVER (
             PARTITION BY amount, customer_number
             ORDER BY groupid
             RANGE BETWEEN 7 FOLLOWING AND UNBOUNDED FOLLOWING
           )
           AS next_groupid
  FROM   data d
)
START WITH groupid = min_groupid
CONNECT BY PRIOR amount          = amount
AND        PRIOR customer_number = customer_number
AND        PRIOR next_groupid    = groupid

, которые выводят:

AMOUNT | CUSTOMER_NUMBER | GROUPID | MAX_GROUPID
:----- | --------------: | ------: | ----------:
1000+  |            5555 |      51 |          57
1000+  |            5555 |      60 |          66
1000+  |            5555 |      69 |          75
2000+  |            6666 |      55 |          61

Запрос 2 :

Считает группы:

SELECT amount,
       customer_number,
       COUNT(*)
FROM   (
  SELECT d.*,
         MIN( groupid )
           OVER ( PARTITION BY amount, customer_number )
           AS min_groupid,
         MIN( groupid )
           OVER (
             PARTITION BY amount, customer_number
             ORDER BY groupid
             RANGE BETWEEN 7 FOLLOWING AND UNBOUNDED FOLLOWING
           )
           AS next_groupid
  FROM   data d
)
START WITH groupid = min_groupid
CONNECT BY PRIOR amount          = amount
AND        PRIOR customer_number = customer_number
AND        PRIOR next_groupid    = groupid
GROUP BY amount, customer_number

, которые выводят:

AMOUNT | CUSTOMER_NUMBER | COUNT(*)
:----- | --------------: | -------:
1000+  |            5555 |        3
2000+  |            6666 |        1

db <> скрипка здесь

0 голосов
/ 31 января 2020

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

Один из способов сделать это:

Select amount, customer_number, sum(seqf) as seqf 
from
  (Select amount, customer_number, 
          case when sum(case when seqf>= 2 then 1 end) >= 1 then 1 end as seqf 
     from
       (Select t.*, 
               Row_number() over(partition by amount, customer_number order by groupid) as rn
          From your_table t)
        Group by amount, customer_number, trunc((rn-1)/7))
Group by amount, customer_number;

Cheers !!

...