Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10

Как получить из поля уникальный список символов?

04.07.2024, 15:15. Показов 746. Ответов 15

Студворк — интернет-сервис помощи студентам
Приветствую!
Собственно, всё содержится в названии темы) Нужно максимально быстро (без цикла по символам каждой строки поля) получить уникальный список символов.

Желательно, результат получить в поле временной таблицы: одна строка = один символ.
То есть, если в поле исходной таблицы всего 2 строки: Маша и Вася, то на выходе нужно получить временную таблицу с одним полем и 6ю строками: М, а, ш, В, с, я.
Регистр имеет значение: символы Д и д являются разными (бинарный калейт).

Возможно, имеет смысл свести к задачу только к получению символов из строки быстрее, чем в цикле по символам. Строки поля можно сцепить в одну огромную строку (насколько огромную, опять же), символы из неё поместить в новую таблицу и потом сгруппировать это поле.

Можно вместе с символами помещать их юникоды — группировка по интам должны быть намного быстрее.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.07.2024, 15:15
Ответы с готовыми решениями:

Как отредактировать список допустимых символов поля username при регистрации???
При регистрации в поле "Логин" вводится e-mail (поменял в languages/common/russian.php надпись). Свойство этого поля осталось username. А...

2 уникальный поля ? или как это сделать?
Здравствуйте. table(accs) newid (PRIMERY KEY) | name | units | price | ip Помогите написать запрос. Если в таблице есть такая...

Как получить уникальный ID
Здравствуйте, нужно получать подряд ID(0, ... n, n+1) для объектов, если объект был удалён, то ID освобождается и при создании нового...

15
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
04.07.2024, 15:23
Написать аналог string_split умеющий разбивать строку посимвольно, а дальше дело техники )
0
 Аватар для Дядя Виля
42 / 34 / 9
Регистрация: 12.06.2024
Сообщений: 168
04.07.2024, 15:39
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
declare @tabl table (fild varchar(100))
 
insert into @tabl values ('Маша'),('Вася')
 
select * from @tabl;
 
with sss
as
(select isnull(t.fild,'') as f, 1 as i, SUBSTRING(isnull(t.fild,''),1,1) fi
from @tabl t
union ALL
select f, sss.i+1, SUBSTRING(f,i+1,1)
from sss
WHERE LEN(sss.f)>=sss.i+1
)
select distinct fi
from sss
1
1304 / 358 / 97
Регистрация: 14.10.2022
Сообщений: 1,089
04.07.2024, 15:53
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Use tempdb
go
 
Create table #t (txt varchar(255))
go
 
insert into #t (txt) 
Values ('Вася'), ('Маша')
 
; With N as (Select t.n N From (Values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) t(n)),
NN as (Select ROW_NUMBER() over (order by 1/0) NN from N a cross join N b cross join N c)
Select distinct SUBSTRING(a.txt, b.NN, 1) collate Cyrillic_General_BIN2 ch
from
    #t a
    Cross join NN b
Where NN<=len(a.txt)
1
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
04.07.2024, 16:00  [ТС]
Дядя Виля, uaggster, благодарю, господа!
Отпишусь по тестам скорости...

Аватар, если не брать интеграцию сторонних языков, то я только циклом такое себе представляю.
0
 Аватар для Дядя Виля
42 / 34 / 9
Регистрация: 12.06.2024
Сообщений: 168
04.07.2024, 16:05
uaggster прав... проверил на другом сервере, collate желателен...
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
declare @tabl table (fild varchar(100))
 
insert into @tabl values ('МашаТт'),('ВасяЯ')
 
select * from @tabl;
 
with sss
as
(select isnull(t.fild,'') as f, 1 as i, SUBSTRING(isnull(t.fild,''),1,1) collate Cyrillic_General_BIN2 fi
from @tabl t
union ALL
select f, sss.i+1, SUBSTRING(f,i+1,1) collate Cyrillic_General_BIN2
from sss
WHERE LEN(sss.f)>=sss.i+1
)
select distinct fi
from sss
могу только добавить, что в его случае желательно еще в конце
T-SQL
1
drop table #t
0
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
04.07.2024, 16:10  [ТС]
uaggster, а кросс n as c точно нужен? Вроде, не участвует...
0
1304 / 358 / 97
Регистрация: 14.10.2022
Сообщений: 1,089
04.07.2024, 16:17
Если буквы, например, только русские, можно так:
T-SQL
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
Use tempdb
go
 
Create table #t (txt varchar(255) collate Cyrillic_General_BIN2)
go
 
insert into #t (txt) 
Values ('Вася'), ('Маша')
 
; With s as (
Select * from (Values
 ('А')
,('Б')
,('В')
,('Г')
,('Д')
,('Е')
,('Ж')
,('З')
,('И')
,('Й')
,('К')
,('Л')
,('М')
,('Н')
,('О')
,('П')
,('Р')
,('С')
,('Т')
,('У')
,('Ф')
,('Х')
,('Ц')
,('Ч')
,('Ш')
,('Щ')
,('Ъ')
,('Ы')
,('Ь')
,('Э')
,('Ю')
,('Я')
,('а')
,('б')
,('в')
,('г')
,('д')
,('е')
,('ж')
,('з')
,('и')
,('й')
,('к')
,('л')
,('м')
,('н')
,('о')
,('п')
,('р')
,('с')
,('т')
,('у')
,('ф')
,('х')
,('ц')
,('ч')
,('ш')
,('щ')
,('ъ')
,('ы')
,('ь')
,('э')
,('ю')
,('я')
) t(ch)
)
Select Distinct a.ch 
from s a Cross join #t b
Where b.txt <> Replace(b.txt, a.ch, '') collate Cyrillic_General_BIN2
Ну или прикрутить табличку, типа master..spt_values

Цитата Сообщение от Jack Famous Посмотреть сообщение
uaggster, а кросс n as c точно нужен? Вроде, не участвует...
Эта порнография:
T-SQL
1
2
With N as (Select t.n N From (Values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) t(n)),
NN as (Select ROW_NUMBER() over (order by 1/0) NN from N a cross join N b cross join N c)
Нужна только для того, чтобы получить роусет с числами от 1 до 1000.
Ну, точнее нужно от 0 до 254, где 254 - это длина txt.

Эту последовательность можете генерировать как угодно.
Может у вас 22 и там вообще generate_series есть.
1
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
04.07.2024, 16:33  [ТС]
uaggster, нужен метод, работающий в полном диапазоне: от 1 до 65 535 кода. Что нужно для этого изменить?
0
1304 / 358 / 97
Регистрация: 14.10.2022
Сообщений: 1,089
04.07.2024, 16:50
Лучший ответ Сообщение было отмечено Jack Famous как решение

Решение

T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Use tempdb
go
 
Create table #t (txt nvarchar(255) collate Cyrillic_General_BIN2)
go
 
insert into #t (txt) 
Values (N'Вася'), (N'Маша')
 
; With s as (
Select NCHAR(ROW_NUMBER() over (order by 1/0) - 1) collate Cyrillic_General_BIN2 ch from string_split(replicate(Cast(' ' as varchar(max)), 65535), ' ')
)
Select Distinct a.ch 
from s a Cross join #t b
Where b.txt <> Replace(b.txt, a.ch, '') collate Cyrillic_General_BIN2
Добавлено через 52 секунды
Но, думаю, в этом случае, первый вариант - лучше.
2
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
04.07.2024, 16:51  [ТС]
uaggster, большое спасибо!
Забыл ваш трюк со сплитом)
А почему Bin2, а не Bin?
0
1304 / 358 / 97
Регистрация: 14.10.2022
Сообщений: 1,089
04.07.2024, 17:01
Цитата Сообщение от Jack Famous Посмотреть сообщение
Забыл ваш трюк со сплитом)
в 22 - generate_series.
В других - лучше завести табличку, строк на 1000.
Есть master..spt_values, но лучше свою такую.

BIN2 и BIN: https://sql-ex.ru/blogs/?/Razn... _BIN2.html
1
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
04.07.2024, 17:02  [ТС]
uaggster, большое спасибо!
0
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
05.07.2024, 10:08  [ТС]
Приветствую!
Результаты тестов: с огромным отрывом и вне конкуренции — вариант из #4 от uaggster.
Дядя Виля, благодарю за альтернативные варианты.

Таблица dbo.sku_Sym содержит 2 поля: номер символа по юникоду и сам символ. 1 - 65 535.
Таблица #bad содержит поле text (но не только) с нужными нам строками. Имеет 29 734 строки.
Список символов из них: 806 591. Уникальный список: 216.
T-SQL
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
Drop Table If Exists #tmp, #list;
 
Declare @m Int, @r Int = 0, @s VarChar(1000), @l Int, @n Int, @c Char(1), @t DateTime = GetDate();
 
 
 
Select Row_Number() Over(Order By id) As RN, text
 
Into   #tmp
 
From   #bad
 
 
 
Create Unique Clustered Index RN On #tmp(RN);
 
Select @m = Max(RN) From #tmp;
 
Create Table #list(U Int, C Char(1));
 
 
 
While (@r < @m)
 
       Begin
 
             Set @r = @r + 1;
 
             Select @s = text From #tmp Where RN = @r;
 
             Set @l = DataLength(@s);
 
             Set @n = 0;
 
 
 
             While (@n < @l)
 
                    Begin
 
                           Set @n = @n + 1;
 
                           Set @c = SubString(@s, @n, 1);
 
 
 
                           Insert Into #list(U,           C)
 
                           Select                UniCode(@c), @c  
 
                    End
 
       End
 
 
 
Print Convert(Char(12), GetDate() - @t, 114);  -- 3.5 min
 
---------------------------------------------------------------------------------------------------
 
Create Index U On #list(U) Include(C);  -- 1 sec
 
---------------------------------------------------------------------------------------------------
 
Drop Table If Exists #uniq;
 
Create Table #uniq(U Int Primary Key, C Char(1));
 
Declare @t DateTime = GetDate();
 
 
 
Insert Into #uniq(U, C)
 
Select       U, C
 
From         #list
 
Group By     U, C
 
 
 
Print Convert(Char(12), GetDate() - @t, 114);  -- 2 sec
 
-- ================================================================================================
 
Drop Table If Exists #uniq2;
 
With s As (Select NChar From dbo.sku_Sym)
 
Select       Distinct a.NChar
 
Into         #uniq2
 
From         s             As A
 
Cross Join   #bad   As B
 
Where        (B.text Collate Cyrillic_General_BIN <> Replace(B.text Collate Cyrillic_General_BIN, A.NChar, '') )      -- 5 min
 
-- ================================================================================================
 
Drop Table If Exists #uniq3;
 
With N As (Select UniCode From dbo.sku_Sym)
 
Select       Distinct SubString(A.text, B.UniCode, 1) Collate Cyrillic_General_BIN As NChar
 
Into         #uniq3
 
From         #bad   As A
 
Cross Join   N             As B
 
Where        UniCode <= Len(A.Text)     -- 1 sec
 
-- ================================================================================================
 
Drop Table If Exists #uniq4;
 
With sss As
 
       (
 
             Select t.text As f, 1 as i, SubString(t.text, 1, 1) Collate Cyrillic_General_BIN As fi
 
             From   #bad As t
 
             Union All
 
             Select f, sss.i + 1, SubString(f, i + 1, 1) Collate Cyrillic_General_BIN
 
             From   sss
 
             Where  Len(sss.f) >= sss.i + 1
 
       )
 
Select Distinct fi As NChar
 
Into   #uniq4
 
From   sss
 
Option (MaxRecursion 0)    -- 4 sec
 
-- ================================================================================================
На 54 млн строк (до 300 символов) вариант из #4 отработал за 2.5 минуты.
Уникальный список увеличился несильно: 236 символов.
Если дистинкт убрать, то время работы (внезапно) увеличивается до 4ёх минут и список символов растёт до 636 млн строк.

Ну и да — можно отфильтровать таблицу символов (для получения номеров символов для каждой строки) по максимальной длине строки в поле. И помним, что Len() не учитывает хвостовые пробелы, а DataLength() будут считать байты для NVarChar.
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
05.07.2024, 10:13
А зачем их считаь если не секрет? Считать распределение каждого символа понятно, а список встречавшихся звчем?
0
932 / 365 / 43
Регистрация: 10.05.2021
Сообщений: 1,564
Записей в блоге: 10
05.07.2024, 10:55  [ТС]
Аватар, не считать, а смотреть)
Есть строки с "плохими" символами, отбираемые по маске типа Like '%[^список допустимых]%'.
Нужно посмотреть, какие именно это символы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.07.2024, 10:55
Помогаю со студенческими работами здесь

Как связать между собой два поля (список значений одного поля зависит от значения другого поля)
Есть таблица: предмет, КодТипаМатериала (список), КодМатериала (список) для примера: стул, ткань, чёрное сукно ...

Не обнаружен уникальный индекс для адресуемого поля главной таблицы, хотя стоят ключевые поля
Не понимаю, почему я не могу связать несколько таблиц с одним и тем же ключевым полем.

Как получить уникальный номер ПК?
Здравствуйте! Хочу сделать какую-то простую привязку к ПК. Попробовал достать Mac адрес - антивирусник кричит что там &quot;Malware...

Как получить уникальный код машины
Как получить уникальный код машины?

Как получить уникальный номер браузера?
Как получить уникальный номер браузера?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru