计算在单个查询中可能多次匹配的SQLite行

时间:2018-05-21 08:49:10

标签: sql sqlite

我有一个SQLite表,其中有一列包含每行可能属于的类别。每行都有一个唯一的ID,但可能属于零个,一个或多个类别,例如:

|------------+-------|
| categories | total |
|------------+-------|
| a          | 2     |
| b          | 2     |
| c          | 2     |
| none       | 1     |
|------------+-------|

我希望获得每个类别中有多少项目的计数。换句话说,输出如下:

case

我尝试使用这样的select case when cats like "%a%" then 'a' when cats like "%b%" then 'b' when cats like "%c%" then 'c' else 'none' end as categories, count(*) from test group by categories 语句:

|------------+-------|
| categories | total |
|------------+-------|
| a          | 2     |
| b          | 1     |
| none       | 1     |
|------------+-------|

但问题是这只计算每行一次,因此无法处理多个类别。然后,您将获得此输出:

union

一种可能性是使用与您有类别一样多的select case when cats like "%a%" then 'a' end as categories, count(*) from test group by categories union select case when cats like "%b%" then 'b' end as categories, count(*) from test group by categories union ... 语句:

{{1}}

但这看起来真的很难看,与DRY相反。

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

修复您的数据结构!您应该有一个表格,每个name和每category一行:

create table nameCategories (
    name varchar(255),
    category varchar(255)
);

然后您的查询会很简单:

select category, count(*)
from namecategories
group by category;

为什么您的数据结构不好?以下是一些原因:

  • 列应包含单个值。
  • SQL有很糟糕的字符串功能。
  • 无法优化执行所需操作的SQL查询。
  • SQL具有用于存储列表的出色数据结构。它被称为,而不是字符串

考虑到这一点,这里有一种蛮力方法可以做你想做的事情:

with categories as (
      select 'a' as category union all
      select 'b' union all
      . . .
     )
select c.category, count(t.category)
from categories c left join
     test t
     on ' ' || t.categories || ' ' like '% ' || c.category || ' %' 
group by c.category;

如果您已有一个有效类别表,则不需要CTE。