我有一个带有Tel_num列的master_table。 Tel_num是11位数的数据,如02365785431。现在,当数字按顺序排列时,我必须将min用作start_num,将max用作end_num并填充其关联的line_value。 如果出现以下情况:
Tel_num Line_value
023158100001 V1
023158100002 V1
023158100003 V1
023158100004 V1
023158115645 V2
023158111546 V2
023158111547 V2
023158111617 V2
023158121110 V3
023158121111 V3
然后我想要类似的数字
Start_NUM End_NUM Line_Value
023158100001 023158100004 V1
023158115645 023158111547 V2
023158111617 023158111617 V2
023158121110 023158121111 V3
有人可以帮忙吗?
答案 0 :(得分:1)
这是一种“群岛”问题。这是使用数字和行号之间的差异的解决方案
select line_value, min(tel_num), max(tel_num)
from (select t.*,
( cast(tel_num as number) -
row_number() over (partition by line_value order by tel_num)
) as grp
from t
) t
group by line_value, grp;
之所以有用,是因为当tel_num
值是连续的时,从tel_num
值中减去一个递增的序列会返回一个恒定值。
Here是一个学期。请注意,结果与问题中指定的结果不同,因为023158115645不应与任何其他数字组合。
答案 1 :(得分:0)
您可以使用lag()
来使用累积方法:
select line_value, min(Tel_num), max(Tel_num)
from (select t.*, sum(case when grp > 1 then 1 else 0 end) over (partition by line_value, grp order by Tel_num) as grp1
from (select t.*, coalesce(cast(Tel_num as number) - lag(Tel_num) over (partition by line_value order by Tel_num), 1) as grp
from table t
) t
) t
group by line_value, grp1;
编辑:似乎您只希望对组成Tel_num
进行分组,那么您只需要一个分组:
select line_value, min(Tel_num), max(Tel_num)
from (select t.*, coalesce(cast(Tel_num as number) - lag(Tel_num) over (partition by line_value order by Tel_num), 1) as grp
from table t
) t
group by line_value, grp;
答案 2 :(得分:0)
CREATE TABLE number (vnum varchar(20), number numeric);
INSERT INTO number (vnum, number)
SELECT 'v1', 023158100001 UNION ALL
SELECT 'V1', 023158100002 UNION ALL
SELECT 'V1', 023158100003 UNION ALL
SELECT 'V1', 023158100004 UNION ALL
SELECT 'v2', 023158115645 UNION ALL
SELECT 'V2', 023158111546 UNION ALL
SELECT 'V2', 023158111547 UNION ALL
SELECT 'V2', 023158111617 UNION ALL
SELECT 'V3', 023158121110 UNION ALL
SELECT 'V3', 023158121111 UNION ALL
SELECT 'V3', 023158121112;
SELECT min(number), start_num, max(number), end_num, vnum line_value FROM number GROUP BY vnum;
答案 3 :(得分:0)
您可以使用分层查询:
Oracle设置:
CREATE TABLE master_table ( line_value, tel_num ) AS
SELECT 'V1', '023158100001' FROM DUAL UNION ALL
SELECT 'V1', '023158100002' FROM DUAL UNION ALL
SELECT 'V1', '023158100003' FROM DUAL UNION ALL
SELECT 'V1', '023158100004' FROM DUAL UNION ALL
SELECT 'V2', '023158115645' FROM DUAL UNION ALL
SELECT 'V2', '023158111546' FROM DUAL UNION ALL
SELECT 'V2', '023158111547' FROM DUAL UNION ALL
SELECT 'V2', '023158111617' FROM DUAL UNION ALL
SELECT 'V3', '023158121110' FROM DUAL UNION ALL
SELECT 'V3', '023158121111' FROM DUAL UNION ALL
SELECT 'V3', '023158121112' FROM DUAL;
查询1 :
SELECT CONNECT_BY_ROOT( tel_num ) AS start_num,
tel_num AS end_num,
line_value
FROM master_table m
WHERE CONNECT_BY_ISLEAF = 1
START WITH NOT EXISTS (
SELECT 1
FROM master_table p
WHERE m.line_value = p.line_value
AND TO_NUMBER( m.tel_num ) - 1 = TO_NUMBER( p.tel_num )
)
CONNECT BY PRIOR line_value = line_value
AND PRIOR TO_NUMBER( m.tel_num ) + 1 = TO_NUMBER( m.tel_num )
ORDER BY line_value, start_num;
输出:
START_NUM END_NUM LINE_VALUE
------------ ------------ ----------
023158100001 023158100004 V1
023158111546 023158111547 V2
023158111617 023158111617 V2
023158115645 023158115645 V2
023158121110 023158121112 V3
答案 4 :(得分:0)
Oracle支持公用表表达式(CTE),因此您可以这样做:
with ranked as (
select Line_Value, Tel_Num,
row_number() over (partition by Line_value order by Tel_Num) as rowNum
from master_table
)
, lastRow as (
select Line_Value, max(rowNum) as lastRow
from ranked
group by Line_Value
)
select fn.Tel_Num, ln.Tel_Num, fn.Line_Value
from ranked fn
inner join ranked ln on fn.Line_Value = ln.Line_value
inner join lastRow lr on ln.Line_Value = lr.Line_Value and ln.rowNum = lr.lastRow
where fn.rowNum = 1
order by fn.Line_Value
说明: