如何使用 SQL 查询去重技巧去除重复数据?

抱歉,我们来谈谈 SQL 查询重复数据删除。
对于这个话题,我们还需要从实际操作开始。

让我们从简单的事情开始:使用 DISTINCT 关键字。
这个东西就像一个筛子,可以过滤掉重复的值。
例如,我们有一个用户表,如果我们想查看每个用户购买了什么,我们需要先删除重复项,对吧?编写方法是 SELECT DISTINCT column_name FROM table_name;这里,column_name是我们想要查看的列的名称。

我们来谈谈 GROUP BY 子句。
这将根据一列或多列将结果集拆分为堆栈。
通常与聚合函数结合使用,例如 SUM、COUNT 等。
例如,如果我们想查看每个用户购买了多少东西,我们需要按用户进行分组,然后进行统计。
写法为SELECT column_name FROM table_name GROUP BY column_name;这里,column_name 是我们分组的列的名称。

还有左连接(LEFT JOIN)加聚合函数。
这个技巧适用于从多个表中恢复数据,然后删除重复项。
例如,如果我们想从两个订单表中查看每个用户购买了什么,我们必须首先将左侧的两个表连接起来,然后使用聚合函数,例如MAX(),以确保每个用户只出现一次。
写法是SELECT a。
FROM to LEFT JOIN (SELECT sid, MAX(tracking_number) AS Tracking_number FROM b GROUP BY sid) b ON a.sid = b.sid;这里a和b是表名,sid是用户ID,tracking_number是订单号。

ROW_NUMBER() 窗口函数也很有用。
这个东西可以给每一行分配一个唯一的序列号。
例如,如果我们想查看每个用户的购买记录中的第一条记录,我们可以使用它。
写法为WITH RankData AS (SELECT, ROW_NUMBER() OVER (PARTITION BY column_name ORDER BY some_column) AS rn FROM table_name) SELECT FROM RankData WHERE rn = 1 ;这里,column_name是分组列的名称,some_column是排序列的名称。

还有 EXISTS 或 DOES NOT EXIST。
这两件事用于检查重复项。
例如,如果我们想查看每个用户的第一次购买记录,我们可以使用NOT EXISTS。
写法为 SELECT FROM table_name t1 WHERE NOT EXISTS (SELECT 1 FROM table_name t2 WHERE t1 .column_name = t2 .column_name AND t1 .id < t2>
最后请注意,不同数据库的语法可能会有所不同。
使用聚合函数或窗口函数时,需要考虑性能问题,尤其是在处理大型数据集时。
在设计查询时,您还需要考虑是否需要保留所有列的数据,或者是否可以通过仅选择所需的列来简化重复数据删除过程。
说实话,当时我并不明白其中的秘密,但是后来我逐渐明白了。

SQL中的三种去重方式:DISTINCT,GROUP BY与ROW_NUMBER()

那么前两天帮同事看报表数据,发现在统计用户访问次数的时候,很明显有一个用户一天只访问一次。
结果,它在报告中多次出现。
经调查发现,导入时数据存在重复。
这让我想起了数据库重复数据删除的重要性。

当时他正在使用DISTINCT。
简单粗暴,直接写SELECT DISTINCT user_id from log_table就可以了。
结果相当快,几分钟内就完成了运行,但随着数据量的增加,他们抱怨滞后。
我告诉他,如果表中的 user_id 列基本上是唯一的,那么使用 DISTINCT 会更有效。
如果表很大,或者需要同时查看其他列,DISTINCT就不够了。

后来我让他们尝试 Group By。
编写了一个 SELECT user_id, COUNT() FROM log_table GROUP BY user_id。
这次结果正确,用户访问数全是1 她问我为什么,我说GROUP BY将具有相同user_id的行合并为一行,并且自动去除重复。
但请注意,如果仅按 user_id 分组,如果其他列中有重复,这些重复列中的数据将被丢弃。
例如user_id 1 2 3 的记录基本上有两条记录,一条是源web,一条是源app。
分组后,只剩下一条记录。
哪个来源就看运气了。

最后,我教他使用 ROW_NUMBER。
它更加灵活。
假设我们要查找每个用户最近一次访问的记录如果我们愿意,我们可以写: SQL 选择A。
从 ( 选择, ROW_NUMBER() OVER (PARTITION BY user_id, ORDER BY Visit_time DESC) AS rn 来自日志表 ) 一个 其中a.rn = 1 ;
该语句首先将每个user_id的记录按visit_time降序排列,rn为序号。
然后外层WHERE rn=1 选择每个用户visit_time最大的记录,即最新的访问记录。
这种方法的好处是你可以定义自己的去重规则,比如按时间、按IP、按设备……调整为顺序即可。
不过,这种方法比前两种方法要复杂一些,而且运行速度可能会慢一些,尤其是当数据量很大的时候。

所以,DISTINCT很简单,GROUP BY很灵活但是需要注意列的选择,ROW_NUMBER很强大但是写的时候需要小心。
使用哪一种取决于您的数据特征和要求。
归根结底,减肥没有最好的方法,只有最合适的方法。

等一下,我刚刚查看了 ROW_NUMBER SQL 和 INTERNAL PARTITION BY user_id ORDER BY Visit_time DESC。
如果visit_time是字符串格式的日期,例如'2 02 3 -1 0-2 7 ',那么这个顺序会按照字典顺序而不是实际时间顺序排序吗?必须尝试一下。