处理PostgreSQL中设计糟糕的"变量列"表

Ore*_*ail 3 sql postgresql

我正在处理一个设计糟糕的桌子,有点像这样

create table (
   entity_key  integer,
   tag1        varchar(10),
   tag2        varchar(10),
   tag3        varchar(10),
   ...
   tag25       varchar(10)
);
Run Code Online (Sandbox Code Playgroud)

实体可以具有由非空列的数量指示的0个或更多个标签.标签都是相同的类型,应该有一个单独的"标签"表,我们可以加入主要实体.

但是,我坚持使用这个(非常大的)表.

我想运行一个查询,它给出了不同的标签和每个标签的计数.

如果我们有标准的"标签"表,我们可以简单地写

select tag, count(tag) from tags group by tag;
Run Code Online (Sandbox Code Playgroud)

但是,鉴于当前的表结构,我还没有为这个查询提出一个好的方法.

a_h*_*ame 5

你可以通过使用数组和不需要的:

select x.tag, count(*)
from tags
    cross join lateral unnest(array[tag1, tag2, tag3, tag4, tag5, tag6, tag7, ...]) as x(tag)
where x.tag is not null --<< git rid of any empty tags
group by x.tag;
Run Code Online (Sandbox Code Playgroud)

这将按标签列的内容进行分组,这与Prdp的答案不同,后者按列列表中的" 位置 "进行分组.

对于此示例数据:

insert into tags (entity_key, tag1, tag2, tag3, tag4, tag5)
values
(1, 'sql', 'dbms', null, null, null),
(2, 'sql', 'dbms', null, null, 'dml'),
(3, 'sql', null, null, 'ddl', null);
Run Code Online (Sandbox Code Playgroud)

这将返回:

tag  | count
-----+------
dml  |     1
ddl  |     1
sql  |     3
dbms |     2
Run Code Online (Sandbox Code Playgroud)