【问题标题】:Filter with multivalue columns in Redshift/SQL在 Redshift/SQL 中使用多值列进行过滤
【发布时间】:2018-02-06 16:07:56
【问题描述】:

我有一张放着新闻文章的桌子。这些新闻文章有许多描述标题、图片等的栏目。一些列可以有多个值,例如类别可以设置为“运动”和“曲棍球”。

假设我有这张桌子:

articlekey | category
---------------------
article1   | sports, hockey  

实际表格包含很多文章,所有文章只出现一次。我试图实现的是在这个表上过滤类别的两个值。为了能够做到这一点,我将它们分成了几行并生成了一个过滤表,如下所示:

articlekey | category
---------------------
article1   | sports
article1   | hockey

(顺便说一句。我们使用 Tableau 作为可视化/BI 工具,这就是我过滤的地方)

当我将这些加入表格并仅在“曲棍球”上过滤(包含)时,我会得到正确的结果,因为文章 1 只有一行的类别设置为“曲棍球”。

articlekey | category         | category-filter
-----------------------------------------------
article1   | sports, hockey   | sports          <-- this will be excluded
article1   | sports, hockey   | hockey          <-- this is included

但是,如果我尝试排除“曲棍球”,则该文章将显示为“体育”类别,因为它会保留在“体育”类别的结果中。结果我希望它完全排除文章。

articlekey | category         | category-filter
-----------------------------------------------
article1   | sports, hockey   | sports          <-- this is included, but should also be gone
article1   | sports, hockey   | hockey          <-- this will be excluded

如果可能,当我每列有多个值并且需要过滤(包括和排除)以便每篇文章只剩下一行时,我应该如何处理这样的数据。

【问题讨论】:

  • 我正在使用 Redshift

标签: sql amazon-redshift tableau-api


【解决方案1】:

我。如果您对类别具有“标准化”数据结构,即类别字段中没有多个值(例如在您的“过滤器表”中):

我认为解决此问题的首选方法是将 1 替换为“曲棍球”,将 0 替换为其他所有内容,然后按 articlekey 将这些数字汇总到组中。总和为 0 的文章键是没有“曲棍球”类别的文章。

所以这是对没有“曲棍球”类别的文章的查询:

select articlekey
from articles 
group by articlekey 
having sum(case when category = 'hockey' then 1 else 0 end) = 0;

您可以概括这一点:例如,如果您需要既不包含“曲棍球”也不包含“运动”但同时包含“足球”和“拳击”类别的文章:

select articlekey
from articles 
group by articlekey 
having sum(
  case when category = 'hockey' then 1
       when category = 'sports' then 1
       else 0 
  end
) = 0
and sum(
  case when category = 'soccer' then 1
       when category = 'boxing' then 1
       else 0 
  end
) = 2;

但你也可以 1.按类别过滤(曲棍球) 2.按articleKey分组 3.计数匹配 4. 左加入

所以这是另一个解决方案:

select * from articles left join (
  select articlekey, count(articlekey) as countOfHockey 
  from articles where category = 'hockey' group by articlekey
) hhh on articles.articlekey=hhh.articlekey where countOfHockey is null;

Sql 小提琴:http://sqlfiddle.com/#!17/27ae1/33

二。如果您有非规范化的类别字段,即类别列表作为逗号分隔的值列表(如在您的原始表中),您可以在它们上使用类似 %% 运算符的 SQL 并编写如下查询:

create table if not exists articles(articlekey varchar, category varchar);
insert into articles values('article1', 'sports, hockey');
insert into articles values('article2', 'sports');
insert into articles values('article3', 'soccer, boxing, sprint');
insert into articles values('article4', 'soccer, sprint');

select * from articles where ', '||category||',' not like '%, hockey,%';

如果您需要既不包含“曲棍球”也不包含“运动”但同时包含“足球”和“拳击”类别的文章,您也可以对此进行概括:

select * from articles where 
', '||category||',' not like '%, hockey,%' and
', '||category||',' not like '%, sports,%' and
', '||category||',' like '%, soccer,%' and
', '||category||',' like '%, boxing,%';

但是请注意,这种方法通常不是在关系数据库中处理数据的首选方法。

【讨论】:

  • 感谢您的快速响应。我会调查一下。
  • 谢谢@riskop。这很有帮助:)
猜你喜欢
  • 2021-11-08
  • 2015-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-16
  • 2014-01-09
  • 2021-01-29
  • 2021-08-27
相关资源
最近更新 更多