Мне нужно реализовать ниже логику через один SQL-запрос - PullRequest
0 голосов
/ 30 августа 2018

У меня есть master_table со столбцом Tel_num. 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

Может кто-нибудь помочь, пожалуйста ???

Ответы [ 5 ]

0 голосов
/ 30 августа 2018

Oracle поддерживает Common Table Expressions (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

Пояснение:

  • отсортировать Tel_Nums в порядке возрастания для каждого значения Line_Value и назначить им номер строки
  • найти последнее значение rowNum для каждого Line_Value
  • конечный результат будет составной из этих
    • ranked, где rowNum = 1, даст вам первый Tel_Num для этого Line_Value
      • Я назвал это fn для First Number
    • ранжируется, присоединяется к lastRow, даст вам последний Tel_Num для этого Line_Value
      • Я назвал это как ln для последнего номера
  • вам нужно объединить все это с помощью Line_Value, чтобы мы получили одну выходную строку на Line_Value
  • вы хотите, чтобы он был отсортирован по Line_Value
0 голосов
/ 30 августа 2018

Вы можете использовать иерархический запрос:

Установка 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
0 голосов
/ 30 августа 2018

Вы можете использовать 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;
0 голосов
/ 30 августа 2018
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;
0 голосов
/ 30 августа 2018

Это тип проблемы групп и островов. Вот решение, использующее разницу между номером и номером строки

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 являются последовательными.

Здесь - тестер. Обратите внимание, что результаты отличаются от указанных в вопросе, потому что 023158115645 не следует объединять с любыми другими числами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...