我试图编写一个查询,给出两个字符串之间不匹配字母的总数。
例如,我有两个字符串
字符串1:Jamess字符串2:Romeeo
我需要找出第二个字符串中不在第一个字符串中匹配的字母总数。
这些信件将是
R,o,o和e
(请注意,第一个字符串只有一个e,因此Romeeo中的额外e不会在字符串1中匹配)。
简而言之,这些字母(R,o,o和e)不存在于字符串1中。
是否可以在Oracle SQL中解决此问题?
答案 0 :(得分: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
答案 1 :(得分: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>
答案 2 :(得分: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;
分享并享受。
答案 3 :(得分:-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 =@Notmatchstring +' '+SUBSTRING(@string2,@count,1)
END
IF(@index>0)
BEGIN
SET @string1=REPLACE(@string1,SUBSTRING(@string2,@count,1),'')
END
SET @count=@count+1
END
SELECT @Notmatchstring as NotMatchingCharacter