Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет количества уникальных значений в строке / 25 сообщений из 36, страница 1 из 2
19.08.2019, 08:55
    #39850919
abort
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Есть строка 2222224444466
нужно вывести
1) используемых символов: 2,4,6
2) кол-во уникальных: 3
...
Рейтинг: 0 / 0
19.08.2019, 09:03
    #39850923
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Код: plsql
1.
2.
3.
4.
with s as (select '2222224444466' str from dual)
select distinct substr(str, level, 1) c
from s
connect by level <= length(str);
...
Рейтинг: 0 / 0
19.08.2019, 11:24
    #39850990
MirnyiAtom
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Код: plsql
1.
2.
3.
4.
5.
with s as (select '2222224444466' str from dual)
select distinct substr(str, level, 1) symb, count(substr(str, level, 1)) over(partition by substr(str, level, 1)) co
       ,count(distinct substr(str, level, 1)) over(partition by str) u_sum
from s
connect by level <= length(str);
...
Рейтинг: 0 / 0
19.08.2019, 12:05
    #39851022
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
MirnyiAtom,

Сейчас придет Elic и будет ругать тебя за группировку через distinct с аналитикой. 👻
...
Рейтинг: 0 / 0
19.08.2019, 13:03
    #39851064
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
abortЕсть строка 2222224444466
Код: plsql
1.
2.
3.
4.
5.
SQL> select regexp_replace('2222224444466', '(.)\1+', '\1') from dual;

REG
---
246

...
Рейтинг: 0 / 0
19.08.2019, 13:10
    #39851071
abort
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Elic,

вот! Ждал именно от этого метода regexp_replace. Но не смог выжать.
Всем спасибо за правильные ответы!
...
Рейтинг: 0 / 0
19.08.2019, 13:30
    #39851087
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
abortвот! Ждал именно от этого метода regexp_replace. Но не смог выжать.Ты понимаешь магию исходных данных?
...
Рейтинг: 0 / 0
19.08.2019, 13:38
    #39851094
mRdUKE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
abortвот! Ждал именно от этого метода regexp_replace. Но не смог выжать.При условии, что сортировка внутри строки сохранится (посимвольная).
...
Рейтинг: 0 / 0
19.08.2019, 13:43
    #39851097
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
mRdUKEabortвот! Ждал именно от этого метода regexp_replace. Но не смог выжать.При условии, что сортировка внутри строки сохранится (посимвольная).

сначала '222222444446622244440' отсортировать, потом посчитать

....
stax
...
Рейтинг: 0 / 0
19.08.2019, 13:54
    #39851102
Vint
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
abort,
зачем тебе тут sql? решай через pl\sql и проще и на магию можно не полагаться)
...
Рейтинг: 0 / 0
19.08.2019, 13:54
    #39851103
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
На малом словаре и длинных строках эффективнее этот словарь джоинить на строку.
...
Рейтинг: 0 / 0
19.08.2019, 14:20
    #39851122
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
with q (val) as (select '2a42w776242224444466' from dual)

select regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1') as "Используемые символы"
, length(regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1')||',')/2 as "Кол-во уникальных"
from q
connect by substr(val,level,1) is not null
...
Рейтинг: 0 / 0
19.08.2019, 14:50
    #39851140
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
интересно, есть ли вариант быстрее, чем PL/SQL функция?

на моем тестовом наборе она оказалась быстрее:
тестовые данные
Код: plsql
1.
2.
3.
create table t_str as
select round(dbms_random.value(1e10,9e10)) str from dual connect by level<=1e5
/

PL/SQL вариант
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
with
  function ff(s varchar2) return varchar2 
  as
      type avarchars is table of varchar2(100) index by varchar2(1);
      st  avarchars;
      idx varchar2(1);
      res varchar2(10);
      
      function iterate( idx in out nocopy varchar2, arr in out nocopy avarchars) 
         return boolean
      as --pragma inline;
      begin
         if idx is null
            then idx:=arr.first; 
            else idx:=arr.next(idx);
         end if;
         return idx is not null;
      end;  
   begin
     for i in 1..length(s) loop
        st(substr(s,i,1)):=1;
     end loop;
     while iterate(idx,st) loop
        res:=res||idx;
     end loop;
     return res;
   end;

select min(ff(str)) res
from t_str
/

SQL вариант
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select min(fstr)
from t_str t
     cross apply (
     select listagg(c) within group (order by 1) fstr
     from (select
            distinct substr(t.str, level, 1) c
           from dual
           connect by level <= length(t.str)
          )
     )
/



с таймингом
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
SQL> create table t_str as
  2  select round(dbms_random.value(1e10,9e10)) str from dual connect by level<=1e5
  3  /

Table created.

Elapsed: 00:00:00.55
SQL> with
  2    function ff(s varchar2) return varchar2
  3    as
  4        type avarchars is table of varchar2(100) index by varchar2(1);
  5        st  avarchars;
  6        idx varchar2(1);
  7        res varchar2(10);
  8
  9        function iterate( idx in out nocopy varchar2, arr in out nocopy avarchars)
 10           return boolean
 11        as --pragma inline;
 12        begin
 13           if idx is null
 14              then idx:=arr.first;
 15              else idx:=arr.next(idx);
 16           end if;
 17           return idx is not null;
 18        end;
 19     begin
 20       for i in 1..length(s) loop
 21          st(substr(s,i,1)):=1;
 22       end loop;
 23       while iterate(idx,st) loop
 24          res:=res||idx;
 25       end loop;
 26       return res;
 27     end;
 28
 29  select min(ff(str)) res
 30  from t_str
 31  /

RES
--------------------------------------------------------------
0123

Elapsed: 00:00:00.48
SQL> select min(fstr) res2
  2  from t_str t
  3       cross apply (
  4       select listagg(c) within group (order by 1) fstr
  5       from (select
  6              distinct substr(t.str, level, 1) c
  7             from dual
  8             connect by level <= length(t.str)
  9            )
 10       )
 11  /

RES2
--------------------------------------------------------------
0123

Elapsed: 00:00:01.01

...
Рейтинг: 0 / 0
19.08.2019, 14:59
    #39851145
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
конечно, если ограничиться только цифрами, то translate получится проще и быстрее всего:
Код: plsql
1.
2.
select min(translate('0123456789', translate('z0123456789','z'||str,'z'), chr(0)))
from t_str
...
Рейтинг: 0 / 0
19.08.2019, 15:03
    #39851147
Vint
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
xtender,
мне кажется ты на вызове функции и ифах теряешь.
может вместо:
Код: plsql
1.
2.
3.
while iterate(idx,st) loop
        res:=res||idx;
     end loop;


попробовать
Код: plsql
1.
2.
3.
for idx in st.first..st.last loop
 res:=res||idx;
end loop;


ну и если быть совсем честным, то надо убрать еще неявное преобразование
Код: plsql
1.
2.
3.
type avarchars is table of varchar2(100) index by varchar2(1);
заменив на 
type avarchars is table of number index by varchar2(1);


сорри. в этой подсети нет оракла, а на сайт лезть влом. :)
...
Рейтинг: 0 / 0
19.08.2019, 15:08
    #39851152
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Vint
Код: plsql
1.
st.first..st.last

смотри внимательно: это ассоциативный массив, в котором в ключах хранятся символы из строки.
...
Рейтинг: 0 / 0
19.08.2019, 15:10
    #39851154
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Vintну и если быть совсем честным, то надо убрать еще неявное преобразованиеособой разницы не будет, но проще, конечно, изменить на varchar2(1) а в приравнивании сделать null вместо 1, т.е:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
with
  function ff(s varchar2) return varchar2 
  as
      type avarchars is table of varchar2(1) index by varchar2(1);
      st  avarchars;
      idx varchar2(1);
      res varchar2(10);
      
      function iterate( idx in out nocopy varchar2, arr in out nocopy avarchars) 
         return boolean
      as --pragma inline;
      begin
         if idx is null
            then idx:=arr.first; 
            else idx:=arr.next(idx);
         end if;
         return idx is not null;
      end;  
   begin
     for i in 1..length(s) loop
        st(substr(s,i,1)):=null;
     end loop;
     while iterate(idx,st) loop
        res:=res||idx;
     end loop;
     return res;
   end;

select min(ff(str)) res
from t_str
/

...
Рейтинг: 0 / 0
19.08.2019, 15:10
    #39851155
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Dshedoo,

я неуверен что поведение order by null не зависит от версии
раньше заблуждался, считая что order by null не будет сортировать

имхо, луче явно указывать поле сортировки

.....
stax
...
Рейтинг: 0 / 0
19.08.2019, 15:24
    #39851169
Dshedoo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
Stax,

Согласен, лучше всегда всё указывать явно.

Но в данном случае, нам же без разницы по какому полю будет сортировка, главное, чтобы оно было одинаковым для всех partition by val.
А если я правильно понимаю, то order by null на разных версиях будет всегда однороден для всех записей?
Никаких же рандомов и прочего?
Я почему-то считал, что order by null = order by null'овое поле.
...
Рейтинг: 0 / 0
19.08.2019, 15:27
    #39851172
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
DshedooЯ почему-то считал, что order by null = order by null'овое поле.Именно поэтому ничего не гарантирует.
...
Рейтинг: 0 / 0
19.08.2019, 15:44
    #39851192
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
DshedooStax,

Согласен, лучше всегда всё указывать явно.

Но в данном случае, нам же без разницы по какому полю будет сортировка, главное, чтобы оно было одинаковым для всех partition by val.
А если я правильно понимаю, то order by null на разных версиях будет всегда однороден для всех записей?
Никаких же рандомов и прочего?
Я почему-то считал, что order by null = order by null'овое поле.

мож я неправильно понял Вашу регулярку
если листагг не отсортирует, то не отработает и regexp_replace

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
  1  with q (val) as (select '2a42w776242224444466' from dual)
  2  select
  3  regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1') as "Используемые символы"
  4  , length(regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1')||',')/2 as "Кол-во уникальных"
  5  ,regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by level),'([^,]+)(,\1)+', '\1') as "Без сортіровки"
  6  from q
  7* connect by substr(val,level,1) is not null
SQL> /

Используемые символы
--------------------------------------------------------------------------------
Кол-во уникальных
-----------------
Без сортіровки
--------------------------------------------------------------------------------
2,4,6,7,a,w
                6
2,a,4,2,w,7,6,2,4,2,4,6



к стати на апексе
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with q (val) as (select '2a42w776242224444466' from dual)
select
regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1') as "Используемые"
, length(regexp_replace(listagg(substr(val,level,1),',') WITHIN GROUP (order by null),'([^,]+)(,\1)+', '\1')||',')/2 as "Кол-во"
from q
connect by substr(val,level,1) is not null
/
Используемые	Кол-во
2,a,4,2,w,7,6,2,4,2,4,6	12
1 rows returned in 0.00 seconds	        	Download



ps
в новых версиях distinct добавили в listagg, тогда и регулярки не надо

.....
stax
...
Рейтинг: 0 / 0
19.08.2019, 16:56
    #39851219
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
xtenderконечно, если ограничиться только цифрами, то translate получится проще и быстрее всего:
Код: plsql
1.
2.
select min(translate('0123456789', translate('z0123456789','z'||str,'z'), chr(0)))
from t_str

супер
...
Рейтинг: 0 / 0
19.08.2019, 17:44
    #39851248
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
xtender
Код: plsql
1.
2.
select min(translate('0123456789', translate('z0123456789','z'||str,'z'), chr(0)))
from t_str


Не будем останавливаться на пол-дороги :)
Код: plsql
1.
translate('0123456789', translate(chr(0)||'0123456789',chr(0)||str,chr(0)), chr(0))
...
Рейтинг: 0 / 0
19.08.2019, 17:56
    #39851254
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
andrey_anonymous,

не в ту сторону ты двинулся :) надо было вместо chr(0) последнего просто 'z' воткнуть - так намного короче
...
Рейтинг: 0 / 0
19.08.2019, 17:58
    #39851256
Vint
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет количества уникальных значений в строке
xtender,
сорри, не доглядел. вот что значит пара месяцев без единой строчки кода)
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет количества уникальных значений в строке / 25 сообщений из 36, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]