有没有直接的方法通过 SQL 查询来做到这一点?
我相信以下将直接产生唯一名称的计数:-
WITH
splt(value,rest) AS
(
SELECT
substr(names,1,instr(names,',')-1),
substr(names,instr(names,',')+1)||','
FROM thetable
UNION ALL SELECT
substr(rest,1,instr(rest,',')-1),
substr(rest,instr(rest,',')+1)
FROM splt
WHERE length(rest) > 0
LIMIT 20 /* just in case limit to 20 iterations increase if more iterations exected */
),
intermediate AS
(
SELECT count(*),
group_concat(value)
FROM splt
WHERE length(value) > 0
GROUP BY value
)
SELECT count(*) AS unique_names FROM intermediate;
说明
这假设国家在一个列中,而名称在另一列中,并且列名是名为 thetable
的表中的
names
查询由 2 个 CTE(公用表表达式,基本上是临时表)组成。
第一个名为 splt 的 CTE 是递归的,它将列表中的每个名称提取为一行。
请注意,递归 CTE 必须具有确定何时停止迭代 WHERE 子句或 LIMIT 的方法。在两者都使用的情况下,当提取值的长度大于 0 时,WHERE 子句是停止迭代(基于每个源行)的正确检查。LIMIT 20 是一种预防措施,当然它可能是增加了。
名为 intermediate 的第二个 CTE 然后通过使用 splt CTE 的结果根据值分组来删除长度为 0 的名称和重复项。
最后统计剩余行数。
演示
使用以下来演示:-
DROP TABLE IF EXISTS thetable;
CREATE TABLE IF NOT EXISTS thetable (country TEXT, names TEXT);
INSERT INTO thetable VALUES
('Germany','Peter,Jan,David,Florian'),
('USA','James,Joe,Bob,David,Alan,George'),
('UK','George,Jack,Peter'),
('Isreal','David,Moshe,Chaim'),
/*<<<<< ADDED to test resillience*/
('Spain',''),
('France',null),
('Italy',zeroblob(100))
;
WITH
splt(value,rest) AS
(
SELECT
substr(names,1,instr(names,',')-1),
substr(names,instr(names,',')+1)||','
FROM thetable
UNION ALL SELECT
substr(rest,1,instr(rest,',')-1),
substr(rest,instr(rest,',')+1)
FROM splt
WHERE length(rest) > 0
LIMIT 20 /* just in case limit to 20 iterations increase if more iterations exected */
),
intermediate AS
(
SELECT count(*),
group_concat(value)
FROM splt
WHERE length(value) > 0
GROUP BY value
)
SELECT count(*) AS unique_names FROM intermediate;
DROP TABLE IF EXISTS thetable;
结果:-