2017-09-25 36 views
2

例如,下面的表的幫助下,要計數的特定值之間的圖案的發生Oracle表

Rn ID Pattern 
1 C20 
2 C21 
3 C25 
4 C25 
5 C25 
6 C25 
7 C25 
8 C21 
9 C23 
10 C20 
11 C21 
12 C25 
13 C25 
14 C25 
15 C22 
16 C21 
17 C20 

我要計數各C20之間的C25圖案。

結果應該是這樣,

- >C25 B/N第一計數和C20 = 5
第二發生見下文參考

Rn ID Pattern 
1 C20 
2 C21 
3 C25 
4 C25 
5 C25 
6 C25 
7 C25 
8 C21 
9 C23 
10 C20 

- C25 B的>計數/ n第二次和第三次出現C20 = 3

10 C20 
11 C21 
12 C25 
13 C25 
14 C25 
15 C22 
16 C21 
17 C20 

T提前。

+0

哪些Oracle數據庫版本?或者你真的認爲'[mysql]'?請注意數據庫標記:答案通常需要特定於某個特定數據庫產品的語法,這可能就是這種情況。 – APC

回答

1

使用與IGNORE NULLS選項LAG解析函數在你的範圍開始找以前的行,然後使用COUNT分析功能與一系列窗口得到計數:

SQL Fiddle

的Oracle 11g R2架構設置

CREATE TABLE table_name (rn, id) AS 
    SELECT 1, 'C20' FROM DUAL UNION ALL 
    SELECT 2, 'C21' FROM DUAL UNION ALL 
    SELECT 3, 'C25' FROM DUAL UNION ALL 
    SELECT 4, 'C25' FROM DUAL UNION ALL 
    SELECT 5, 'C25' FROM DUAL UNION ALL 
    SELECT 6, 'C25' FROM DUAL UNION ALL 
    SELECT 7, 'C25' FROM DUAL UNION ALL 
    SELECT 8, 'C21' FROM DUAL UNION ALL 
    SELECT 9, 'C23' FROM DUAL UNION ALL 
    SELECT 10, 'C20' FROM DUAL UNION ALL 
    SELECT 11, 'C21' FROM DUAL UNION ALL 
    SELECT 12, 'C25' FROM DUAL UNION ALL 
    SELECT 13, 'C25' FROM DUAL UNION ALL 
    SELECT 14, 'C25' FROM DUAL UNION ALL 
    SELECT 15, 'C22' FROM DUAL UNION ALL 
    SELECT 16, 'C21' FROM DUAL UNION ALL 
    SELECT 17, 'C20' FROM DUAL; 

查詢1

SELECT * 
FROM (
    SELECT t.*, 
     COUNT(CASE id WHEN 'C25' THEN 1 END) 
      OVER (ORDER BY rn 
        ROWS BETWEEN (rn - prev_rn) PRECEDING AND CURRENT ROW) 
      AS num_c25 
    FROM (
    SELECT t.*, 
      LAG(CASE id WHEN 'C20' THEN rn END, 1, 1) 
      IGNORE NULLS OVER (ORDER BY rn) AS prev_rn 
    FROM table_name t 
) t 
) 
WHERE id = 'C20' 

Results

| RN | ID | PREV_RN | NUM_C25 | 
|----|-----|---------|---------| 
| 1 | C20 |  1 |  0 | 
| 10 | C20 |  1 |  5 | 
| 17 | C20 |  10 |  3 | 

另一種方法是使用分層查詢:

查詢2

SELECT * 
FROM (
    SELECT t.*, 
     COUNT(CASE id WHEN 'C25' THEN 1 END) OVER (ORDER BY rn ROWS BETWEEN LEVEL - 1 PRECEDING AND CURRENT ROW) AS num_c25, 
     CONNECT_BY_ROOT rn AS start_rn, 
     CONNECT_BY_ISLEAF AS isleaf 
    FROM table_name t 
    START WITH id = 'C20' 
    CONNECT BY PRIOR rn + 1 = rn 
    AND id <> 'C20' 
) 
WHERE isleaf = 1 

Results

| RN | ID | NUM_C25 | START_RN | ISLEAF | 
|----|-----|---------|----------|--------| 
| 9 | C23 |  5 |  1 |  1 | 
| 16 | C21 |  3 |  10 |  1 | 
| 17 | C20 |  0 |  17 |  1 | 
相關問題