SQL Server查询-保留组的第一和最后唯一记录

时间:2019-02-20 16:40:41

标签: sql sql-server duplicates

我们正在尝试删除系统的每日供稿中提供的表格中的数据并对其进行排名。示例数据当然不是实际产品,但可以清楚地表示概念。

每日插入:

  1. 每天将数据导入表中,这些表会不断更新产品状态
  2. 每日状态更新会告诉我们产品何时上市,当前是否上市以及最后上市的日期
  3. 经过{X}时间后,我们可以将数据归一化

清理和排名:

  1. 我们现在正尝试删除第一个值和最后一个值之间的组中重复值的记录

  2. 我们还希望为代表该组中唯一值的第一个和最后一次出现的记录设置标识符。

样本数据:

enter image description here 我发现照片是显示数据,显示需要和不需要的东西的最简单方法-我希望这可以使照片变得更简单而不是晦涩。

在示例数据中:

  • “ ridgerapp”我们要保留17年3月12日和17年12月12日的记录。
  • “ ridgerapp”,我们要删除介于上述日期之间的记录。
  • “ ridgerapp”,我们还希望设置/更新03/12/17和06/12/17的记录作为第一次和最后一次出现-类似于-
  • 更新表集03/12/17 = 0(第一个),06/12/17 = 1(最后)

  • “ sierra”只是另一个扩展的数据示例,我们希望保留16/12/16和12/11/16的记录。

  • “ sierra”删除16年6月12日至16年12月11日之间的记录。
  • “ sierra”将16/12/16和12/11/16记录的状态/排名更新为第一次和最后一次出现。
  • 更新表集12/06/16 = 0(第一个),12/11/16 = 1(最后)。

结论:

使用伪代码,这是总体目标:

  • 在表中选择不同的记录(使用id,名称,颜色,值作为唯一标识符)
  • 对于每个组中的记录,请查看历史记录,并找到最晚和最晚的日期
  • 删除每个组的最高日期和最低日期之间的记录
  • 使用状态和等级(字段名称为等级)将每个组中的值更新为0和1的历史记录
  • 使用样本数据,结果将结束

更新的表值:

 23  ridgerapp  blue    25  03/12/17    0
 23  ridgerapp  blue    25  06/12/17    1
 57  sierra     red     15  12/06/16    0
 57  sierra     red     15  12/11/16    1

1 个答案:

答案 0 :(得分:0)

我将通过CTE窗口函数使用row_number()来查找每个 group 的第一行和最后一行,然后对其进行更新。

您未指定是什么使 group 成为 group ,所以我仅基于ID。如果您希望该组是一组列,即IDColorValue,则只需将这些列添加到partition by列表中。对于样本数据,结果将是相同的,但是不同的样本数据将具有不同的结果。

注意,我没有为sierra组添加确切的行,因为我想向您展示如何处理重复的history日期。

declare @table table (id int, [name] varchar(64), color varchar(16), [value] int, history date)
insert into @table
values
(23,'ridgerapp','blue',25,'20170312'),
(23,'ridgerapp','blue',25,'20170325'),
(23,'ridgerapp','blue',25,'20170410'),
(23,'ridgerapp','blue',25,'20170610'),
(23,'ridgerapp','blue',25,'20170612'),

(57,'sierra','red',15,'20161206'),
(57,'sierra','red',15,'20161208'),
(57,'sierra','red',15,'20161210'),
(57,'sierra','red',15,'20161210')   --notice this is a duplicate row

;with cte as(
select 
    *
    ,fst = row_number() over (partition by id order by history asc)
    ,lst = row_number() over (partition by id order by history desc)
from @table
)

delete from cte
where fst !=1 and lst !=1

select 
    *
    ,flag = case when row_number() over (partition by id order by history asc) = 1 then 0 else 1 end
from @table

退货

+----+-----------+-------+-------+------------+------+
| id |   name    | color | value |  history   | flag |
+----+-----------+-------+-------+------------+------+
| 23 | ridgerapp | blue  |    25 | 2017-03-12 |    0 |
| 23 | ridgerapp | blue  |    25 | 2017-06-12 |    1 |
| 57 | sierra    | red   |    15 | 2016-12-06 |    0 |
| 57 | sierra    | red   |    15 | 2016-12-10 |    1 |
+----+-----------+-------+-------+------------+------+