[英]SQL Query that counts the number of characters match in two text columns
我需要計算兩個文本列(相同大小,在同一個表中)中有多少個字符相等。 例如:
RowNum: Template: Answers:
------- --------- --------
1 ABCDEABCDEABCDE ABCDAABCDBABCDC
2 EDAEDAEDAEDAEDA EDBEDBEDBEDBEDB
SELECT SOME_COUNT_FUNCTION (Template, Answers) 應該返回:
RowNum: Result:
------- -------
1 12
2 10
數據庫是一個 MySQL。
不完全是 MySQL,但這里有一些適用於 SQL Server 的東西。 也許它會翻譯過來。
DROP TABLE IF EXISTS #tmp
CREATE TABLE #tmp (
[RowNum] INT IDENTITY(1,1) PRIMARY KEY,
[Template] NVARCHAR(20),
[Answer] NVARCHAR(20),
[Result] INT
)
INSERT INTO #tmp
VALUES ('ABCDEABCDEABCDE','ABCDAABCDBABCDC', NULL),
('EDAEDAEDAEDAEDA','EDBEDBEDBEDBEDB', NULL)
--SELECT * FROM #tmp
DECLARE @current_template NVARCHAR(50) -- Variable to hold the current template
, @current_answer NVARCHAR(50) -- Variable to hold the current answer
, @template_char CHAR(1) -- Char for template letter
, @answer_char CHAR(1) -- Char for answer letter
, @word_index INT -- Index (position) within each word
, @match_counter INT -- Match counter for each word
, @max_iter INT = (SELECT TOP 1 RowNum FROM #tmp ORDER BY RowNum DESC) -- Max iterations
, @row_idx INT = (SELECT TOP 1 RowNum FROM #tmp) -- Minimum RowNum as initial row index value.
WHILE (@row_idx <= @max_iter)
BEGIN
SET @match_counter = 0 -- Reset match counter for each row
SET @word_index = 1 -- Reset word index for each row
SET @current_template = (SELECT [Template] FROM #tmp WHERE RowNum = @row_idx)
SET @current_answer = (SELECT [Answer] FROM #tmp WHERE RowNum = @row_idx)
WHILE (@word_index <= LEN(@current_template))
BEGIN
SET @template_char = SUBSTRING(@current_template, @word_index, 1)
SET @answer_char = SUBSTRING(@current_answer, @word_index, 1)
IF (@answer_char = @template_char)
BEGIN
SET @match_counter += 1
END
SET @word_index += 1
END
UPDATE #tmp
SET Result = @match_counter
WHERE RowNum = @row_idx
SET @row_idx += 1
END
從臨時表中獲取值:
SELECT * FROM #tmp
輸出:
RowNum Template Answer Result
1 ABCDEABCDEABCDE ABCDAABCDBABCDC 12
2 EDAEDAEDAEDAEDA EDBEDBEDBEDBEDB 10
如果您運行的是 MySQL 8.0,則可以使用遞歸查詢逐個字符比較字符串:
with recursive chars as (
select rownum, template, answers, 1 idx, 0 res from mytable
union all
select
rownum,
template,
answers,
idx + 1,
res + ( substr(template, idx, 1) = substr(answers, idx, 1) )
from chars
where idx <= least(char_length(template), char_length(answers))
)
select rownum, max(res) result from chars group by rownum order by rownum
在CTE( with
子句)中,anchor( union all
之前的查詢)選擇全表,然后遞歸成員( union all
之后的查詢)比較字符,當前位置( idx
)遞增結果( res
)如果它們匹配,則前進到下一個位置,直到(最小的)字符串用完。 然后,外部查詢僅按rownum
聚合。
rownum | result -----: | -----: 1 | 12 2 | 10
請記住,此查詢對大型數據集的性能不佳。 存在其他稍微更有效的解決方案(通常使用數字表而不是遞歸 cte),但基本上,正如 Gordon Linoff 所評論的,如果您需要運行此類查詢,您確實希望修復您的數據結構。 您應該將每個字符以及它的rownum
和它在字符串中的索引存儲在一個單獨的行中。 物化為合適的數據結構,然后你就不需要生成它在每一個查詢的飛行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.