创建 VIEW 以根据最大日期从表中删除重复项

Creating a VIEW to remove duplicates from table based on max date

提问人:Python_Hey 提问时间:7/20/2022 最后编辑:Python_Hey 更新时间:7/21/2022 访问量:177

问:

我有一个表格,它每天附加数据并记录导入的日期,但它会附加重复项。

我在这里的最终目标是根据最低导入的列日期删除重复项。

以下是该表的初始状态:

表客户端

名字
鲍勃 John 18-07-2022
玛尔塔 18-07-2022
莱恩 麦克斯 18-07-2022
鲍勃 John 20-07-2022
玛尔塔 20-07-2022
莱恩 麦克斯 20-07-2022
布莱恩 20-07-2022

所需状态:

名字
鲍勃 John 18-07-2022
玛尔塔 18-07-2022
莱恩 麦克斯 18-07-2022
布莱恩 20-07-2022

我想如果我可以在所有行上创建一个视图并匹配,我会在其中删除 MAX(导入的)列?虽然不确定这是否是正确的方法。

一旦我使用 MAX 列创建视图:

CREATE VIEW CLIENTS_VIEW AS
SELECT * FROM CLIENTS
WHERE "Imported" = ( SELECT MAX("Imported") FROM CLIENTS);

虽然不确定我现在如何匹配原始表上的视图并仅保留每个导入列的最小值?

SQL 数据库 snowflake-cloud-data-platform 数据操作

评论

1赞 Dean Flinter 7/20/2022
可能有几种方法,但您如何确定唯一客户?您需要它才能获得每个客户端的最低值
0赞 Python_Hey 7/20/2022
所有列的匹配是否是一个合适的解决方案?实际表格看起来与示例略有不同,尽管不确定我是否每行都存在一个完全唯一的列。
0赞 Dean Flinter 7/20/2022
根据示例,所有列都无法正常工作,因为您希望过滤其中一个列。您当然可以使用姓名+姓氏,但总是存在具有相同名称的不同客户端的潜力,从而破坏了任何解决方案。理想情况下,每个客户都有一个唯一的密钥,但考虑到这一点,我会给出一些可能的解决方案
1赞 Greg Pavlik 7/21/2022
您有 和 的标签。他们使用不同的 SQL 方言。你需要哪一个?mysqlsnowflake-cloud-data-platform
0赞 Python_Hey 7/21/2022
@GregPavlik 好点子,我现在已经换了,那是雪花

答:

1赞 Himanshu Kandpal 7/20/2022 #1

您可以尝试的一种方法是使用分析功能,

select * from (
select column1 as Name, column2 as Surname, column3 as Imported, row_number() over (partition by Name, surname order by imported desc) rnum from values
('Bob','John','18-07-2022'),
 ('Marta','White','18-07-2022'),
 ('Ryan','Max','18-07-2022'),  
('Bob','John','20-07-2022'),  
('Marta','White','20-07-2022'), 
('Ryan','Max','20-07-2022'),  
('Brian','Red','20-07-2022')
  ) where rnum = 1;
  
1赞 Dean Flinter 7/20/2022 #2

正如我在评论中提到的,理想情况下,每个客户端都有一个唯一的标识符。缺少它,我将使用 name||'_'||surname 作为伪主键。

您可以在此处使用几种方法

第一种是使用子查询来联接键和导入的日期

CREATE VIEW CLIENTS_VIEW AS
SELECT C.* FROM CLIENTS C
JOIN
    (
SELECT 
name||'_'||surname as client_name
, MAX(imported) as latest
FROM CLIENTS
GROUP BY 1
     ) MI ON MI.client_name = C.name||'_'||surname AND MI.latest = C.imported

另一种方法是根据另一个答案使用行号函数

CREATE VIEW CLIENTS_VIEW AS
SELECT C.* FROM CLIENTS C
QUALIFY row_number() over (partition by Name, surname order by imported desc)=1

根据我的经验,如果数据量很大,子查询的性能会更高

还有其他替代方法,例如使用 NOT EXISTS、重新加入到同一表或使用 CTE

对于较大的表,性能最高的选项是为每个客户端创建另一个包含最新数据的表(同样需要唯一标识符),并定期使用 MERGE 更新插入新数据。

像这样的东西

merge into clients_latest cl using (select * from clients) as c on 
cl.name||'_'||surname = c.name||'_'||surname
when matched then update set cl.imported = c.imported
when not matched then insert (name, surname, imported) values (c.name, 
c.surname, c.imported);

如果此数据不经常更改,则半定期计划任务可以为您运行此数据。如果不断追加表,则仅追加表流可能是一个更快的选择,因为您只会在上次更新插入后对新数据进行更新插入