如果我有这样的桌子
Number Status ------ ------ 1 A 2 A 3 A 4 U 5 U 6 A 7 U 8 U 9 A 10 A
我可以使用什么查询将范围分组为Status = A的范围?
Range Count Status ----- ----- ------ 1-3 3 A 6-6 1 A 9-10 2 A
我的查询是
select min(number) || '--' || max(number), count(*), Status from table where Status = 'A' group by Status Range Count Status ----- ----- ------ 1-10 6 A
这是一个很好的方法,由Aketi Jyuuzou命名,名称为“ Tabibitosan method ”。
SQL> WITH data AS 2 (SELECT num - DENSE_RANK() OVER(PARTITION BY status ORDER BY num) grp, 3 status, 4 num 5 FROM t 6 ) 7 SELECT MIN(num) 8 ||' - ' 9 || MAX(num) range, 10 COUNT(*) cnt 11 FROM data 12 WHERE status='A' 13 GROUP BY grp 14 ORDER BY grp 15 / RANGE CNT ------ ---------- 1 - 3 3 6 - 6 1 9 - 10 2 SQL>
注意 最好使用DENSE_RANK以避免重复。
DENSE_RANK
桌子
SQL> SELECT * FROM t ORDER BY num; NUM S ---------- - 1 A 1 A 2 A 2 A 3 A 4 U 5 U 6 A 7 U 8 U 9 A NUM S ---------- - 10 A 12 rows selected.
num = 1重复。
使用 DENSE_RANK :
SQL> WITH data AS 2 (SELECT num - DENSE_RANK() OVER(PARTITION BY status ORDER BY num) grp, 3 status, 4 num 5 FROM t 6 ) 7 SELECT MIN(num) 8 ||' - ' 9 || MAX(num) range, 10 COUNT(*) cnt 11 FROM data 12 WHERE status='A' 13 GROUP BY grp 14 ORDER BY grp 15 / RANGE CNT ------ ---------- 1 - 3 5 6 - 6 1 9 - 10 2 SQL>
使用 ROW_NUMBER :
SQL> WITH DATA AS 2 (SELECT num - ROW_NUMBER() OVER(PARTITION BY status ORDER BY num) grp, 3 status, 4 num 5 FROM t 6 ) 7 SELECT MIN(num) 8 ||' - ' 9 || MAX(num) range, 10 COUNT(*) cnt 11 FROM data 12 WHERE status='A' 13 GROUP BY grp 14 ORDER BY grp 15 / RANGE CNT ------ ---------- 2 - 3 2 1 - 2 2 1 - 6 2 9 - 10 2 SQL>
因此,如果重复,则 ROW_NUMBER 查询将给出错误的结果。您应该使用 DENSE_RANK 。