У меня есть две строки, первая выглядит так: 24,36,78,98. второй такой: 25,36,88,98
Теперь я хочу сравнить две строки в sql и вернуть только те числа, которые одинаковы в каждой строке.
Возможно ли это в sql или мне нужно написать свою собственную функцию, например PL/SQL?
Я погуглил, но не нашел ответов на этот вопрос.


Это можно сделать в sql или pl/sql в зависимости от ваших потребностей:
Если в вашей базе данных установлен Oracle APEX, у вас есть APEX_STRING API, который вы можете использовать для преобразования строки в массив. Затем используйте оператор MULTISET, чтобы получить пересечение значений:
set serveroutput on size 999999
clear screen
DECLARE
l_string1 VARCHAR2(100) := '24,36,78,98';
l_string2 VARCHAR2(100) := '25,36,88,98';
l_string_intersect VARCHAR2(100);
l_string1_arr apex_t_varchar2;
l_string2_arr apex_t_varchar2;
l_intersect_arr apex_t_varchar2;
BEGIN
l_string1_arr := apex_string.split(l_string1,',');
l_string2_arr := apex_string.split(l_string2,',');
l_intersect_arr := l_string1_arr MULTISET INTERSECT l_string2_arr;
l_string_intersect := apex_string.join(l_intersect_arr,',');
dbms_output.put_line('intersect values: '||l_string_intersect);
END;
/
PL/SQL procedure successfully completed.
intersect values: 36,98
Без APEX, и если вам все еще нужен pl/sql, используйте технику sql для разделения (см. ниже) и используйте оператор MULTISET для получения пересечения.
для sql, посмотрите этот блог о различных методах разделения строки, разделенной запятыми, на значения.
Вот пример того, как это сделать, используя технику, описанную в блоге выше:
with
string1 as (
select '24,36,78,98' str from dual
),
string2 as (
select '25,36,88,98' str from dual
),
string1_tab as (
select regexp_substr (
str,
'[^,]+',
1,
level
) value
from string1
connect by level <=
length ( str ) - length ( replace ( str, ',' ) ) + 1
),
string2_tab as (
select regexp_substr (
str,
'[^,]+',
1,
level
) value
from string2
connect by level <=
length ( str ) - length ( replace ( str, ',' ) ) + 1
)
select * from string1_tab
INTERSECT
select * from string2_tab
;
Еще один вариант (выглядит довольно просто), который разбивает строку на строки, чтобы можно было применить оператор набора пересечений.
Образец данных:
SQL> with test (col1, col2) as
2 (select '24,36,78,98', '25,36,88,98' from dual)
Запрос начинается здесь:
3 select regexp_substr(col1, '[^,]+', 1, level) val
4 from test
5 connect by level <= regexp_count(col1, ',') + 1
6 intersect
7 select regexp_substr(col2, '[^,]+', 1, level) val
8 from test
9 connect by level <= regexp_count(col2, ',') + 1;
VAL
-----------
36
98
SQL>
Еще один с XQuery:
with data(a,b) as (
select '24,36,78,98', '25,36,88,98' from dual
)
select t.* from
data d,
xmltable(
'for $i in (ora:tokenize($X,",")), $j in (ora:tokenize($Y,",")) where ($i = $j) return $i'
passing a as "X", b as "Y"
columns val number path '.'
) t
;
Ваше воображение — единственный предел для изобретения других... С 23c вы даже можете использовать MLE для работы с функцией Javascript в массивах JSON:
export function intersect(arr1string, arr2string) {
let arr1 = eval(arr1string == null? [] : arr1string);
let arr2 = eval(arr2string == null? [] : arr2string);
return arr1.filter(n => arr2.includes(n));
}