SQL按多值字符串列中的不同值分组
Posted
技术标签:
【中文标题】SQL按多值字符串列中的不同值分组【英文标题】:SQL grouping by distinct values in a multi-value string column 【发布时间】:2019-03-25 01:49:14 【问题描述】:(我想根据具有多个值的字符串列中的不同值执行分组
该列有一个标准格式的字符串列表,用逗号分隔。潜在值仅为a,b,c,d
。
例如列collection
(类型:字符串)包含:
Row 1: ["a","b"]
Row 2: ["b","c"]
Row 3: ["b","c","a"]
Row 4: ["d"]`
预期的输出是唯一值的计数:
collection | count
a | 2
b | 3
c | 2
d | 1
【问题讨论】:
请用您正在使用的数据库标记您的问题并描述collection
的数据类型。
【参考方案1】:
对于以下所有内容,我都使用了这张表:
create table tmp (
id INT auto_increment,
test VARCHAR(255),
PRIMARY KEY (id)
);
insert into tmp (test) values
("a,b"),
("b,c"),
("b,c,a"),
("d")
;
如果可能的值只有a,b,c,d
,您可以尝试以下方法之一:
请注意,这仅在您没有像test
和test_new
这样相似的值时才有效,因为这样test
也将与所有test_new
行合并,并且计数将不匹配
select collection, COUNT(*) as count from tmp JOIN (
select CONCAT("%", tb.collection, "%") as like_collection, collection from (
select "a" COLLATE utf8_general_ci as collection
union select "b" COLLATE utf8_general_ci as collection
union select "c" COLLATE utf8_general_ci as collection
union select "d" COLLATE utf8_general_ci as collection
) tb
) tb1
ON tmp.test LIKE tb1.like_collection
GROUP BY tb1.collection;
这会给你想要的结果
collection | count
a | 2
b | 3
c | 2
d | 1
或者你可以试试这个
SELECT
(SELECT COUNT(*) FROM tmp WHERE test LIKE '%a%') as a_count,
(SELECT COUNT(*) FROM tmp WHERE test LIKE '%b%') as b_count,
(SELECT COUNT(*) FROM tmp WHERE test LIKE '%c%') as c_count,
(SELECT COUNT(*) FROM tmp WHERE test LIKE '%d%') as d_count
;
结果会是这样的
a_count | b_count | c_count | d_count
2 | 3 | 2 | 1
【讨论】:
【参考方案2】:您需要做的是首先将集合列分解成单独的行(如flatMap
操作)。在redshift中,生成新行的唯一方法是JOIN
- 所以让我们CROSS JOIN
你的输入表带有一个具有连续数字的静态表,并且只取id
小于或等于的表集合中的元素数量。然后我们将使用split_part
函数读取正确索引处的项目。一旦我们有了 exploaded 表,我们将做一个简单的GROUP BY
。
如果您的项目存储为 JSON 数组字符串 ('["a", "b", "c"]'
),那么您可以分别使用 JSON_ARRAY_LENGTH
和 JSON_EXTRACT_ARRAY_ELEMENT_TEXT
而不是 REGEXP_COUNT
和 SPLIT_PART
。
with
index as (
select 1 as i
union all select 2
union all select 3
union all select 4 -- could be substituted with 'select row_number() over () as i from arbitrary_table limit 4'
),
agg as (
select 'a,b' as collection
union all select 'b,c'
union all select 'b,c,a'
union all select 'd'
)
select
split_part(collection, ',', i) as item,
count(*)
from index,agg
where regexp_count(agg.collection, ',') + 1 >= index.i -- only get rows where number of items matches
group by 1
【讨论】:
以上是关于SQL按多值字符串列中的不同值分组的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使指定了所有值,Spark SQL 也会为字符串列打开可为空?
Pandas 数据框:如何按多值列将一行拆分为多行? [复制]
Spark将布尔列与字符串列进行比较与比较值相等的int和字符串的工作方式不同
如何检查 SQL Server 2008 表中字符串列中的 id