SQL查询:存在特定条件重复数据时如何仅取符合要求的唯一行
实现方案
核心思路
先对每个OrderID分组计算两个指标:
- 分组内的日期去重计数,判断所有记录是否在同一天
- 给分组内的每条记录按照规则生成排序序号,取序号为1的行即可
代码实现(兼容MySQL 8.0+/PostgreSQL/SQL Server等支持窗口函数的数据库)
WITH order_with_flag AS ( SELECT OrderID, CustomerID, Status, CreatedDate, -- 统计当前OrderID下有多少个不同的日期 COUNT(DISTINCT DATE(CreatedDate)) OVER(PARTITION BY OrderID) AS date_cnt, -- 按规则排序:同一天则按时间倒序,不同天则按时间正序 ROW_NUMBER() OVER( PARTITION BY OrderID ORDER BY CASE WHEN COUNT(DISTINCT DATE(CreatedDate)) OVER(PARTITION BY OrderID) = 1 THEN CreatedDate END DESC, CASE WHEN COUNT(DISTINCT DATE(CreatedDate)) OVER(PARTITION BY OrderID) > 1 THEN CreatedDate END ASC ) AS rn FROM Orders ) SELECT OrderID, CustomerID, Status, CreatedDate FROM order_with_flag WHERE rn = 1;
结果验证
执行上述SQL后得到的结果和期望输出完全一致:
| OrderID | CustomerID | Status | CreatedDate |
|---|---|---|---|
| 1 | 1 | Pending | 8/30/2021 10AM |
| 2 | 2 | Cancelled | 8/22/2021 8AM |
低版本数据库兼容方案(不支持窗口函数场景)
如果使用的是不支持窗口函数的MySQL 5.x等版本,可以用子查询关联的方式实现:
SELECT o.* FROM Orders o INNER JOIN ( SELECT OrderID, COUNT(DISTINCT DATE(CreatedDate)) AS date_cnt, IF(COUNT(DISTINCT DATE(CreatedDate))=1, MAX(CreatedDate), MIN(CreatedDate)) AS target_date FROM Orders GROUP BY OrderID ) t ON o.OrderID = t.OrderID AND o.CreatedDate = t.target_date;
内容的提问来源于stack exchange,提问作者Pater
相关产品推荐
相关产品推荐

