2014-10-22 2 views
0

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

К примеру, у меня даны две струны

Струнные 1: Jamess Строка 2: Romeeo

Мне нужно, чтобы узнать общее количество букв во второй строке, которые не имеющий совпадение в первой строке.

Буквы бы

R, о, о и е

(обратите внимание, что первая строка содержит только один е, так что дополнительные е в Romeeo не имеющее соответствие в строке 1).

Короче говоря, эти буквы (R, о, о, и е) не существует в строке 1.

Есть прочь, чтобы решить эту проблему в Oracle SQL?

ответ

2

Забавная игра-головоломка;)

Используя аналитическую функцию COUNT() и путем разбиения до текущей строки, вы действительно можете «указать свои буквы»:

SELECT letters, 
     COUNT(*) OVER (PARTITION BY letters ORDER BY n ROWS 
         BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) cnt FROM (
    --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    SELECT SUBSTR('Jameess', LEVEL, 1) letters, LEVEL n FROM DUAL 
    CONNECT BY LEVEL <= LENGTH('Jameess') 
) 

Производство этого результата:

LETTERS CNT 
J  1 -- first J 
a  1 -- first a 
e  1 -- first e 
e  2 -- second e 
m  1 -- ... 
s  1 
s  2 

сделать это один раз для каждой строки, и вы только сравнить каждый буквенный индекс это его собственная группа:

SELECT s2.letters 
FROM (
    SELECT letters, 
     COUNT(*) OVER (PARTITION BY letters ORDER BY n ROWS 
         BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) cnt FROM (
    SELECT SUBSTR('Jameess', LEVEL, 1) letters, LEVEL n FROM DUAL 
    CONNECT BY LEVEL <= LENGTH('Jameess') 
) 
) S1 
RIGHT OUTER JOIN (
    SELECT letters, 
     COUNT(*) OVER (PARTITION BY letters ORDER BY n ROWS 
         BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) cnt FROM (
    SELECT SUBSTR('Romeeeeo', LEVEL, 1) letters, LEVEL n FROM DUAL 
    CONNECT BY LEVEL <= LENGTH('Romeeeeo') 
) 
) S2 
ON s1.letters = s2.letters AND s1.cnt = s2.cnt 
WHERE s1.cnt IS NULL 
-- ^^^^^^ 
-- change to `s2.cnt` to compare your strings the other way around 
-- and replace the RIGHT JOIN by a LEFT JOIN 
ORDER BY letters 

Производство:

LETTERS 
R 
e 
e 
o 
o 

(В целях тестирования добавьте несколько дополнительных e в Jameess и Romeeeeo)

+0

Отличное решение – user311509

-2

Попробуйте этот SQL-запрос

DECLARE @string1 VARCHAR(100)='Jamess' 
DECLARE @string2 VARCHAR(100)='Romeeo' 
DECLARE @Notmatchstring VARCHAR(100) 
SET @Notmatchstring ='' 
DECLARE @index INT 
DECLARE @count INT 

SET @count=1 
WHILE @count <= LEN(@string2) 
BEGIN 

    SET @index=CHARINDEX(SUBSTRING(@string2,@count,1),@string1,0) 

    IF(@index=0) 
    BEGIN 
    SET @Notmatchstring [email protected] +' '+SUBSTRING(@string2,@count,1) 
    END 
    IF(@index>0) 
    BEGIN 
    SET @string1=REPLACE(@string1,SUBSTRING(@string2,@count,1),'') 
    END 
    SET @[email protected]+1 
END 
SELECT @Notmatchstring as NotMatchingCharacter 
+1

Вопрос четко указывает, что используемая база данных - это Oracle, а не SQL Server. Тег [SQL] относится к структурированному языку запросов, а не к продукту Microsoft SQL Server. –

1

В Oracle,

SQL> WITH DATA AS 
    2 (SELECT 'Jamess' str1, 'Romeeo' str2 FROM dual 
    3 ), 
    4 data2 AS 
    5 (SELECT SUBSTR(str1, LEVEL, 1) str1 
    6 FROM DATA 
    7  CONNECT BY LEVEL <= LENGTH(str1) 
    8 ), 
    9 data3 AS 
10 (SELECT SUBSTR(str2, LEVEL, 1) str2 
11 FROM DATA 
12  CONNECT BY LEVEL <= LENGTH(str2) 
13 ) 
14 SELECT * FROM data3 WHERE str2 NOT IN 
15 (SELECT str1 FROM data2 
16 ) 
17 UNION ALL 
18 SELECT str2 
19 FROM data3 
20 WHERE str2 IN 
21 (SELECT str1 FROM data2 
22 ) 
23 GROUP BY str2 
24 HAVING COUNT(*)>1 
25/

S 
- 
R 
o 
o 
e 

SQL> 
0

вопрос помечен [plsql] так что я думал, что решение PL/SQL будет в порядке:

DECLARE 
    stringA VARCHAR2(20) := 'Jamess'; 
    stringB VARCHAR2(20) := 'Romeeo'; 
    strDiff VARCHAR2(20); 

    FUNCTION find_unmatched(p1 IN VARCHAR2, p2 IN VARCHAR2) 
    RETURN VARCHAR2 
    IS 
    s1 VARCHAR2(32767) := p1; 
    s2 VARCHAR2(32767) := p2; 
    s3 VARCHAR2(32767); 
    c CHAR(1); 
    p NUMBER; 
    BEGIN 
    LOOP 
     c := SUBSTR(s2, 1, 1); 

     p := INSTR(s1, c); 
     IF p = 0 THEN -- c not found in s1: add to unmatched list and remove from s2 
     s3 := s3 || c; 
     s2 := SUBSTR(s2, 2); 
     ELSE -- c found in s1: remove from s1 and s2 
     s1 := SUBSTR(s1, 1, p-1) || SUBSTR(s1, p+1, LENGTH(s1)-p); 
     s2 := SUBSTR(s2, 2); 
     END IF; 

     IF s1 IS NULL OR s2 IS NULL THEN 
     EXIT; 
     END IF; 
    END LOOP; 

    RETURN s3; 
    END find_unmatched; 

BEGIN 
    strDiff := find_unmatched(stringA, stringB); 

    DBMS_OUTPUT.PUT_LINE('strDiff=''' || strDiff || ''''); 
END; 

Делите и наслаждайтесь.

Смежные вопросы