在oracle中如何使用OVER(PARTITION BY???)AS计数,当组转换器时,计数应重置为1

xuo3flqw  于 2023-03-22  发布在  Oracle
关注(0)|答案(2)|浏览(128)

我有一个Oracle表,其中有[row,grp and pdate]列,我需要每个[pdate] ]列都不出现[grp]列,如果相同的[grp]在其余的行计数中重复,则应像预期结果[表3]一样得到休息
表数据[表1]

ROW    GRP PDATE     
---------------------- 
0001    361  06-MAR-23
0002    361  07-MAR-23
0003    361  08-MAR-23
0004    417  09-MAR-23
0005    361  10-MAR-23
0006    361  11-MAR-23
0007    362  12-MAR-23
0008    361  13-MAR-23
0009    361  14-MAR-23
0010    361  15-MAR-23
0011    361  16-MAR-23
0012    417  17-MAR-23
0013    417  18-MAR-23
0014    362  19-MAR-23
0015    362  20-MAR-23
0016    362  21-MAR-23

不工作的SQL [表2]

select ROW,GRP,PDATE
,count (1) OVER ( PARTITION BY  A.GRP ORDER BY  A.GRP,A.PDATE) AS COUNT
from t2 a ORDER BY PDATE;

ROW_                   GRP_                   PDATE_                    COUNT                  
---------------------- ---------------------- ------------------------- ---------------------- 
48                     361                    06-MAR-23                 1                      
49                     361                    07-MAR-23                 2                      
34                     362                    08-MAR-23                 1                      
50                     361                    08-MAR-23                 3                      
51                     417                    09-MAR-23                 1                      
35                     362                    09-MAR-23                 2                      
52                     361                    10-MAR-23                 4                      
36                     362                    10-MAR-23                 3                      
53                     361                    11-MAR-23                 5                      
40                     388                    12-MAR-23                 1                      
54                     361                    12-MAR-23                 6                      
55                     361                    13-MAR-23                 7                      
41                     388                    13-MAR-23                 2                      
42                     388                    14-MAR-23                 3                      
56                     361                    14-MAR-23                 8                      
43                     388                    15-MAR-23                 4                      
57                     361                    15-MAR-23                 9

[表3]
预期结果(使用Oracle COUNT(1)OVER(PARTITION BY???order by)AS Count)基于日期中未出现GRP)

ROW     GRP  PDATE     COUNT                  
---------------------- ------
0001    361  06-MAR-23  3
0002    361  07-MAR-23  3
0003    361  08-MAR-23  3
0004    417  09-MAR-23  1
0005    361  10-MAR-23  2
0006    361  11-MAR-23  2
0007    362  12-MAR-23  1 
0008    361  13-MAR-23  4
0009    361  14-MAR-23  4 
0010    361  15-MAR-23  4
0011    361  16-MAR-23  4
0012    417  17-MAR-23  2
0013    417  18-MAR-23  2 
0014    362  19-MAR-23  3 
0015    362  20-MAR-23  3 
0016    362  21-MAR-23  3

目的是创建HTML表格与“colspan”的基础上的结果所给予的计数列

示例输出

---------------------------------------------------------------------------------------------
DATE   |   06-MAR-23 (COLSPAN=3)  |  07-MAR-23 COLSPAN=1 |   08-MAR-23 COLSPAN=3   
---------------------------------------------------------------------------------
AAA    |    361-1 | 361-2 | 361-3 |         417-1        |    361-1  | 361-2
---------------------------------------------------------------------------------
p8ekf7hl

p8ekf7hl1#

在您改变主意并修改了示例表内容之后,它看起来毕竟是关于 islands 的。首先创建“groups”(我的代码中的rn列),然后以其解析形式应用count函数。

SQL> with test (row_, grp, pdate) as
  2    (select '0001', 361, date '2023-03-06' from dual union all
  3     select '0002', 361, date '2023-03-07' from dual union all
  4     select '0003', 361, date '2023-03-08' from dual union all
  5     select '0004', 417, date '2023-03-09' from dual union all
  6     select '0005', 361, date '2023-03-10' from dual union all
  7     select '0006', 361, date '2023-03-11' from dual
  8    ),
  9  temp as
 10    (select row_, grp, pdate,
 11       to_number(row_) - row_number() over (partition by grp order by pdate) rn
 12     from test
 13    )
 14  select row_, grp, pdate,
 15    count(*) over (partition by rn) cnt
 16  from temp
 17  order by pdate;

ROW_        GRP PDATE            CNT
---- ---------- --------- ----------
0001        361 06-mar-23          3
0002        361 07-mar-23          3
0003        361 08-mar-23          3
0004        417 09-mar-23          1
0005        361 10-mar-23          2
0006        361 11-mar-23          2

6 rows selected.

SQL>
c90pui9n

c90pui9n2#

在Oracle 12中,您可以使用MATCH_RECOGNIZE进行逐行模式匹配:

SELECT rw,
       grp,
       pdate,
       COUNT(*) OVER (PARTITION BY mn) AS cnt
FROM   table1
MATCH_RECOGNIZE(
  ORDER BY rw
  MEASURES
    MATCH_NUMBER() AS mn
  ALL ROWS PER MATCH
  PATTERN (same_grp+)
  DEFINE same_grp AS FIRST(grp) = grp
)

其中,对于示例数据:

CREATE TABLE table1 (RW, GRP, PDATE) AS
SELECT '0001', 361, DATE '2023-03-06' FROM DUAL UNION ALL
SELECT '0002', 361, DATE '2023-03-07' FROM DUAL UNION ALL
SELECT '0003', 361, DATE '2023-03-08' FROM DUAL UNION ALL
SELECT '0004', 471, DATE '2023-03-09' FROM DUAL UNION ALL
SELECT '0005', 361, DATE '2023-03-10' FROM DUAL UNION ALL
SELECT '0006', 361, DATE '2023-03-11' FROM DUAL UNION ALL
SELECT '0007', 362, DATE '2023-03-12' FROM DUAL UNION ALL
SELECT '0008', 361, DATE '2023-03-13' FROM DUAL UNION ALL
SELECT '0009', 361, DATE '2023-03-14' FROM DUAL UNION ALL
SELECT '0010', 361, DATE '2023-03-15' FROM DUAL UNION ALL
SELECT '0011', 361, DATE '2023-03-16' FROM DUAL UNION ALL
SELECT '0012', 417, DATE '2023-03-17' FROM DUAL UNION ALL
SELECT '0013', 417, DATE '2023-03-18' FROM DUAL UNION ALL
SELECT '0014', 362, DATE '2023-03-19' FROM DUAL UNION ALL
SELECT '0015', 362, DATE '2023-03-20' FROM DUAL UNION ALL
SELECT '0016', 362, DATE '2023-03-21' FROM DUAL;

输出:
| 放射性同位素|玻璃钢|日期|碳纳米管|
| - ------|- ------|- ------|- ------|
| 零零零一|三六一|2023年3月6日00时00分|三个|
| 小零零零二|三六一|2023年3月7日00时00分|三个|
| 小零零零三|三六一|2023年3月8日00时00分|三个|
| 0004|四百七十一|2023年3月9日00时00分|1个|
| 小零零五|三六一|2023年3月10日00时00分|第二章|
| 小零零零六|三六一|2023年3月11日00时00分|第二章|
| 零零七|三六二|2023年3月12日00时00分|1个|
| 小零零零八|三六一|2023年3月13日00时00分|四个|
| 小零零一一|三六一|2023年3月16日00时00分|四个|
| 小零零一零|三六一|2023年3月15日00时00分|四个|
| 0009|三六一|2023年3月14日00时00分|四个|
| 0012|四一七|2023年3月17日00时00分|第二章|
| 0013|四一七|2023年3月18日00时00分|第二章|
| 0015|三六二|2023年3月20日00时00分|三个|
| 零零四|三六二|2023年3月19日00时00分|三个|
| 小零零一六|三六二|2023年3月21日00时00分|三个|
fiddle
在Oracle 11 g中,您可以用途:

SELECT rw, grp, pdate,
       COUNT(*) OVER (PARTITION BY mn) AS cnt
FROM   (
  SELECT rw, grp, pdate,
         SUM(has_changed) OVER (ORDER BY rw) AS mn
  FROM   (
    SELECT rw, grp, pdate,
           CASE LAG(grp) OVER (ORDER BY rw)
           WHEN grp
           THEN 0
           ELSE 1
           END AS has_changed
    FROM   table1
  )
)

SELECT rw, grp, pdate,
       COUNT(*) OVER (PARTITION BY grp, mn) AS cnt
FROM   (
  SELECT rw, grp, pdate,
         ROW_NUMBER() OVER (ORDER BY rw) - ROW_NUMBER() OVER (PARTITION BY grp ORDER BY rw) AS mn
  FROM   table1
)
ORDER BY rw

或:

SELECT rw, grp, pdate, COUNT(*) OVER (PARTITION BY mn) As cnt
FROM   (
  SELECT *
  FROM   ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY rw) AS rn FROM table1 t )
  MODEL
    DIMENSION BY ( rn )
    MEASURES ( rw, grp, pdate, 1 AS mn )
    RULES (
      mn[rn>1] = mn[cv(rn)-1] + CASE WHEN grp[cv(rn)] = grp[cv(rn)-1] THEN 0 ELSE 1 END
    )
)

输出结果与在更高版本中使用MATCH_RECOGNIZE相同。
fiddle

相关问题