基于最后日期在表间移动记录的有效方法

时间:2014-07-18 19:33:55

标签: sql sql-server

我有一张表来跟踪各种属性之间的关系,以及它们发生的日期。我想看看各个实体之间的关系如何变化。作为分析的一部分,我想移动关系在特定日期结束的记录。

如果数据看起来像这样:

id | FieldOne | FieldTwo | FieldThree |  DataDate 
---------------------------------------------------
01 |    A     |    A     |    A       | 2000-01-01
01 |    A     |    A     |    A       | 2000-01-02
01 |    A     |    A     |    A       | 2000-01-03
01 |    A     |    A     |    A       | 2000-01-04
01 |    A     |    A     |    B       | 2000-01-05
02 |    A     |    C     |    C       | 2000-01-01
02 |    A     |    C     |    C       | 2000-01-02
02 |    A     |    D     |    C       | 2000-01-03
02 |    A     |    D     |    C       | 2000-01-04
02 |    A     |    D     |    C       | 2000-01-05
03 |    C     |    A     |    D       | 2000-01-01
03 |    C     |    A     |    D       | 2000-01-02
03 |    C     |    A     |    D       | 2000-01-03
03 |    C     |    A     |    D       | 2000-01-04
03 |    C     |    A     |    D       | 2000-01-05

我想采取“封闭”记录,并研究/分析它们。

因此,如果我的截止日期是2000-01-05,那么我想删除患者01的所有AAA记录,但不是AAB记录,它仍然是“活跃的”。此外,我想要患者02的ACC记录,但不是ADC记录,而不是患者03的记录。应该保留“活动”记录,以便收集数据的其他进程仍然可以将同一患者的后续记录写入同一个表。

实际表有九列,所有列都是varchars或不同的长度。

目前,我正在通过寻找所有已结束的关系来做这件事,然后做一个难看的连接。

SELECT id, FieldOne, FieldTwo, FieldThree
INTO Closed
FROM DataTable
GROUP BY id, FieldOne, FieldTwo, FieldThree
HAVING MAX( DataDate ) < '2001-01-05'

DELETE d.*
OUTPUT deleted.* 
INTO OutputTable
FROM DataTable d
INNER JOIN Closed c
ON d.Id = c.Id
AND (d.FieldOne = c.FieldOne
  OR (d.FieldOne IS NULL
  AND c.FieldOne IS NULL))
AND (d.FieldTwo = c.FieldTwo
  OR (d.FieldTwo IS NULL
  AND c.FieldTwo IS NULL))
AND (d.FieldThree = c.FieldThree
  OR (d.FieldThree IS NULL
  AND c.FieldThree IS NULL))

我觉得可能有一种更好(更快,更优雅)的方法,但是当我使用EXISTS时,它会返回所有记录,而不是我想要的子集。

实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

这将选择前四列组合在截止日期或之后至少有一条记录的行:

select dt.*
from datatable dt
where exists (select 1
              from datatable dt2
              where dt.id = dt2.id and
                    dt.field1 = dt2.field1 and
                    dt.field2 = dt2.field2 and
                    dt.field3 = dt2.field3 and
                    dt.datadate >= '2001-01-05'
             );

如果值可以有NULL s,那么比较需要考虑到这一点。