我有一个数据集,我正在try 同时以两种方式清理和消除重复数据.

例如,如果我们忽略标点符号(包括空格)、词序和缩写,这些公司名称都是相同的:

 company_id |    company_name    |        words        | words_wo_spaces |    words_sorted     | sorted_words_wo_spaces 
------------+--------------------+---------------------+-----------------+---------------------+------------------------
         17 | the usa co         | {THE,USA,COMPANY}   | THEUSACOMPANY   | {COMPANY,THE,USA}   | COMPANYTHEUSA     
         18 | the u s a company  | {THE,U,S,A,COMPANY} | THEUSACOMPANY   | {A,COMPANY,S,THE,U} | ACOMPANYSTHEU     
         19 | usa company, the   | {USA,COMPANY,THE}   | USACOMPANYTHE   | {COMPANY,THE,USA}   | COMPANYTHEUSA     
         20 | u s a company, the | {U,S,A,COMPANY,THE} | USACOMPANYTHE   | {A,COMPANY,S,THE,U} | ACOMPANYSTHEU     

我有一些助手函数来创建除company_idcompany_name之外的所有列-拆分和排序单词以及重新编码单词以删除常见缩写的函数(例如,将‘co’替换为‘Company’).我要把那些帮助器功能排除在这个问题之外.

如果我们查看列words_wo_spaces,则有两对匹配的公司:17/1819/20. 如果我们按sorted_words_wo_spaces分组,则有两对不同的匹配公司:17/1918/20.

我真正想要的是一个查询(或两个或三个),它可以使用这两种方法对公司进行分组,以确定它们都是相同的.

查询1

SELECT 
  array_agg(company_id) ids
  , array_agg(company_name) names
FROM companies
GROUP BY words_wo_spaces

-- Returns

--    ids   | words_wo_spaces 
-- ---------+-----------------
--  {19,20} | USACOMPANYTHE
--  {17,18} | THEUSACOMPANY

问题2

SELECT 
  array_agg(company_id) ids
  , array_agg(company_name) names
FROM companies
GROUP BY sorted_words_wo_spaces

-- Returns

--    ids   | sorted_words_wo_spaces 
-- ---------+------------------------
--  {18,20} | ACOMPANYSTHEU
--  {17,19} | COMPANYTHEUSA

但我想不出如何将两者结合起来.如果17=18,18=20,17=19,那么它们都是一样的.可以将此逻辑放入SQL查询中吗?

我确实try 了连接这两个查询的结果,但这没有任何帮助(正如预期的那样,一旦我找到了答案).

WITH
  unsorted_groups AS <query 1>
  , sorted_groups AS <query 2>
SELECT 
  array_cat(sorted_groups.ids, unsorted_groups.ids) ids
FROM sorted_groups 
JOIN unsorted_groups 
  ON unsorted_groups.ids && sorted_groups.ids;

-- Returns

--      ids   
-- ---------------
--  {18,20,19,20}
--  {18,20,17,18}
--  {17,19,19,20}
--  {17,19,17,18}

would有用的是一个查询,它将返回这样一个表,这样ID数组就可以被排序,然后用来将所有行组合成一个(这个理想的结果是每个ID都在每行的ids个数组中).

--      ids   
-- ---------------
--  {18,17,19,20}
--  {18,20,17,19}
--  {17,19,18,20}
--  {17,19,20,18}

推荐答案

您可以使用overlap operator &&连接这两个查询,如下所示:

WITH Q1 AS
(
  SELECT 
    array_agg(company_id ORDER BY company_id) ids -- The order by is necessary for the aggregation in the joined query
  FROM companies
  GROUP BY words_wo_spaces
),
Q2 AS
(
  SELECT 
    array_agg(company_id ORDER BY company_id) ids -- The order by is necessary
  FROM companies
  GROUP BY sorted_words_wo_spaces
),
Joined_Q AS
(
  SELECT Q1.ids Q1_ids,
         UNNEST(Q2.ids) Q2_ids -- for each array of ids from q1, unnest the matched array of ids from q2
  FROM Q1 JOIN Q2
  ON Q1.ids && Q2.ids
)
SELECT DISTINCT ARRAY_AGG(Q2_ids ORDER BY Q2_ids) -- aggregate the unnested q2 ids as a single array.
FROM Joined_Q
GROUP BY Q1_ids

Demo

Sql相关问答推荐

如何返回字符串中包含相同值的数据?

Oracle中的分层查询

在Oracle中,如何删除具有特定值的行,仅当它是重复的行?

从日期开始向前填充重复项

将重复的值更新为下一个空闲数字

用户购买平台及金额统计

如何使用SQL Server中的Nodes()方法执行与OPENXML相同的操作

数据库SQL-CTE命名空间(错误?)使用临时视图

将 json 列键映射到第二个表中的匹配列值

在特定条件下使用 LAG,确定要采用什么 LAG 值?

如何在 SQL Server 中解决这个复杂的窗口查询?

根据要过滤的列的值进行联接和分组

INSERT INTO 语法

PostgreSQL-用第一个非空填充以前的值

根据潜在空值的条件对记录进行计数

编写查询以根据级别 (p2) 返回父位置

Select 多年的日期范围

使用 json_agg 从 SQL 查询获取 [null] 响应

从 Pyspark 转换为具有多个分组条件的语句时的情况

遍历数据,计算每个月最后三天的总和