Sql 如何在oracle中选择记录范围中的范围

Sql 如何在oracle中选择记录范围中的范围,sql,oracle,oracle10g,gaps-and-islands,Sql,Oracle,Oracle10g,Gaps And Islands,如果我有一张这样的桌子 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 我

如果我有一张这样的桌子

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 

Oracle 11g R2架构设置

create table x(
  num_ number,
  status_ varchar2(1)
  );

insert into x values(1,'A');
insert into x values(2,'A');
insert into x values(3,'A');
insert into x values(4,'U');
insert into x values(5,'U');
insert into x values(6,'A');
insert into x values(7,'U');
insert into x values(8,'U');
insert into x values(9,'A');
insert into x values(10,'A');
select min(num_) || '-'  || max(num_) range_, status_,
count(1) count_
from
(
  select num_, status_,
  num_ - row_number() over (order by status_, num_) y --gives a group number to each groups, which have same status over consecutive records.
  from x
 )
 where status_ = 'A'
 group by y, status_
 order by range_
| RANGE_ | STATUS_ | COUNT_ |
|--------|---------|--------|
|    1-3 |       A |      3 |
|    6-6 |       A |      1 |
|   9-10 |       A |      2 |
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>
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>
查询1

create table x(
  num_ number,
  status_ varchar2(1)
  );

insert into x values(1,'A');
insert into x values(2,'A');
insert into x values(3,'A');
insert into x values(4,'U');
insert into x values(5,'U');
insert into x values(6,'A');
insert into x values(7,'U');
insert into x values(8,'U');
insert into x values(9,'A');
insert into x values(10,'A');
select min(num_) || '-'  || max(num_) range_, status_,
count(1) count_
from
(
  select num_, status_,
  num_ - row_number() over (order by status_, num_) y --gives a group number to each groups, which have same status over consecutive records.
  from x
 )
 where status_ = 'A'
 group by y, status_
 order by range_
| RANGE_ | STATUS_ | COUNT_ |
|--------|---------|--------|
|    1-3 |       A |      3 |
|    6-6 |       A |      1 |
|   9-10 |       A |      2 |
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>
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>

create table x(
  num_ number,
  status_ varchar2(1)
  );

insert into x values(1,'A');
insert into x values(2,'A');
insert into x values(3,'A');
insert into x values(4,'U');
insert into x values(5,'U');
insert into x values(6,'A');
insert into x values(7,'U');
insert into x values(8,'U');
insert into x values(9,'A');
insert into x values(10,'A');
select min(num_) || '-'  || max(num_) range_, status_,
count(1) count_
from
(
  select num_, status_,
  num_ - row_number() over (order by status_, num_) y --gives a group number to each groups, which have same status over consecutive records.
  from x
 )
 where status_ = 'A'
 group by y, status_
 order by range_
| RANGE_ | STATUS_ | COUNT_ |
|--------|---------|--------|
|    1-3 |       A |      3 |
|    6-6 |       A |      1 |
|   9-10 |       A |      2 |
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>
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>

这是一个很好的方法,Aketi Jyuzu给它起了一个奇特的名字

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>
注意最好使用
密集等级
以避免重复

表格

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存在重复项

使用密度等级:

create table x(
  num_ number,
  status_ varchar2(1)
  );

insert into x values(1,'A');
insert into x values(2,'A');
insert into x values(3,'A');
insert into x values(4,'U');
insert into x values(5,'U');
insert into x values(6,'A');
insert into x values(7,'U');
insert into x values(8,'U');
insert into x values(9,'A');
insert into x values(10,'A');
select min(num_) || '-'  || max(num_) range_, status_,
count(1) count_
from
(
  select num_, status_,
  num_ - row_number() over (order by status_, num_) y --gives a group number to each groups, which have same status over consecutive records.
  from x
 )
 where status_ = 'A'
 group by y, status_
 order by range_
| RANGE_ | STATUS_ | COUNT_ |
|--------|---------|--------|
|    1-3 |       A |      3 |
|    6-6 |       A |      1 |
|   9-10 |       A |      2 |
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>
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>
使用行编号

create table x(
  num_ number,
  status_ varchar2(1)
  );

insert into x values(1,'A');
insert into x values(2,'A');
insert into x values(3,'A');
insert into x values(4,'U');
insert into x values(5,'U');
insert into x values(6,'A');
insert into x values(7,'U');
insert into x values(8,'U');
insert into x values(9,'A');
insert into x values(10,'A');
select min(num_) || '-'  || max(num_) range_, status_,
count(1) count_
from
(
  select num_, status_,
  num_ - row_number() over (order by status_, num_) y --gives a group number to each groups, which have same status over consecutive records.
  from x
 )
 where status_ = 'A'
 group by y, status_
 order by range_
| RANGE_ | STATUS_ | COUNT_ |
|--------|---------|--------|
|    1-3 |       A |      3 |
|    6-6 |       A |      1 |
|   9-10 |       A |      2 |
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>
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>

因此,在重复的情况下,行编号查询将给出不正确的结果。您应该使用密集等级

您能给我们看一下想要的结果吗?您好,先生,关于预期的结果范围计数状态,请参见方框2------------使用密集等级检查的1-3 3 A 6-6 1 A 9-10 2 AAs,我得到的执行时间更短。:)非常感谢。