【问题标题】:Calculate count based on multiple groups of 7 number range in Oracle在Oracle中根据多组7个数字范围计算计数
【发布时间】:2020-01-30 23:05:02
【问题描述】:

谁能帮帮我,我卡在这里了。

给定

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 组 ID)

需要:

如果 SEQF >=2 在 51 到 57 的任何 GROUPID 中的第一个组中,则考虑 COUNT(SEQF) = 1

如果 SEQF >=2 在 58 到 61 的任何 GROUPID 中的第 2 组中,则考虑 COUNT(SEQF) = 1

这里很全面

AMOUNT  CUSTOMER_NUMBER COUNT(SEQF)
1000+       5555                2

如果 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

【问题讨论】:

  • 您使用的是 Oracle 还是 MySQL?你标记了两者,也许是偶然的?如果你用 MySQL,你用的是什么版本?
  • groupid 的组是否已固定,例如第一组总是51到57?还是按groupid 的顺序只装7 个?如果有,是否有差距,如果有差距怎么办——无论差距与否,都取 7?
  • 是的,它是 Oracle。我错误地标记了mysql。它是按 groupid 顺序排列的 7 包。另外,我们必须考虑到要取 7 的差距。

标签: sql oracle count grouping


【解决方案1】:

其他答案都没有解决组之间存在差距的问题(他们只是假设组是连续的)。这将跳过间隙并将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

哪个输出:

数量 | CUSTOMER_NUMBER |组ID | 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

哪个输出:

数量 | CUSTOMER_NUMBER |数数(*) :----- | --------------: | --------: 1000+ | 5555 | 3 2000+ | 6666 | 1

db小提琴here

【讨论】:

    【解决方案2】:

    我认为您需要将 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;
    

    干杯!!

    【讨论】:

      【解决方案3】:

      首先你必须找到 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 demo

      我使用了max(seqf),因为您在任何 GROUPID 中的第一个组中的 IF SEQF >=2 表明了这一点。例如,如果您想要该组中的第一个值,请使用 min ... keep dense rank first


      您还可以为每个 (amount, customer_number) 减去 groupid 和 minimum groupid,除以 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-16
        • 1970-01-01
        • 1970-01-01
        • 2020-07-02
        • 2022-07-22
        • 1970-01-01
        • 2010-12-21
        • 1970-01-01
        相关资源
        最近更新 更多