2012-03-27 108 views
1

我有一些肮脏的资源使用记录t_resourcetable它看起来像这样合并记录

 
resNo subres startdate      enddate 
1  2  2012-01-02 22:03:00.000   2012-01-03 00:00:00.000 
1  2  2012-01-03 00:00:00.000   2012-01-04 00:00:00.000 
1  2  2012-01-04 00:00:00.000   2012-01-04 16:23:00.000 
1  3  2012-01-06 16:23:00.000   2012-01-06 22:23:00.000 
2  2  2012-01-04 05:23:00.000   2012-01-06 16:23:00.000 

我需要那些肮脏行以这样的方式

 
resNo subres startdate      enddate 
1  2  2012-01-02 22:03:00.000   2012-01-04 16:23:00.000 
1  3  2012-01-06 16:23:00.000   2012-01-06 22:23:00.000 
2  2  2012-01-04 05:23:00.000   2012-01-06 16:23:00.000 

被合并这应该得到更新到同一张表,我有超过40k行,所以不能使用游标,请帮我清理这种数据通过一些优化的SQL语句。

提供了temptable和group的解决方案不会遇到类似情况。 我我不基于游标解决方案寻找到这个问题

 
resNo subres startdate      enddate 
1  2  2012-01-02 22:03:00.000   2012-01-03 00:00:00.000 
1  2  2012-01-03 00:00:00.000   2012-01-04 00:00:00.000 
1  2  2012-01-04 00:00:00.000   2012-01-04 16:23:00.000 
1  2  2012-01-14 10:09:00.000   2012-01-15 00:00:00.000 
1  2  2012-01-15 00:00:00.000   2012-01-16 00:00:00.000 
1  2  2012-01-16 00:00:00.000   2012-01-16 03:00:00.000 
1  3  2012-01-06 16:23:00.000   2012-01-06 22:23:00.000 
2  2  2012-01-04 05:23:00.000   2012-01-06 16:23:00.000 

我需要那些肮脏行以这样的方式被合并

 
resNo subres startdate      enddate 
1  2  2012-01-02 22:03:00.000   2012-01-04 16:23:00.000 
1  2  2012-01-14 10:09:00.000   2012-01-16 03:00:00.000 
1  3  2012-01-06 16:23:00.000   2012-01-06 22:23:00.000 
2  2  2012-01-04 05:23:00.000   2012-01-06 16:23:00.000 

plesae带我离开这个肮脏的数据问题

+0

重复:http://stackoverflow.com/questions/9884642/merging-records-from-multiple-rows-in-table-sql-server – 2012-03-27 17:07:21

回答

0

第一步是创建备份:

select * 
into t_resourcetable_backup20120327 
from t_resourcetable 

然后通过resNo编组的第一记录和subRes更新结束日期:

update t_resourcetable 
set enddate = (select max (enddate) 
       from t_resourcetable t1 
       where t1.resNo = t_resourcetable.resNo 
        and t1.subRes = t_resourcetable.subRes) 
where not exists (select null 
       from t_resourcetable t1 
       where t1.resNo = t_resourcetable.resNo 
        and t1.subRes = t_resourcetable.subRes 
        and t1.startdate < t_resourcetable.startdate) 

最后删除多余的记录:

delete t_resourcetable 
where exists (select null 
       from t_resourcetable t1 
       where t1.resNo = t_resourcetable.resNo 
        and t1.subRes = t_resourcetable.subRes 
        and t1.startdate < t_resourcetable.startdate) 

如果您有resNo和subRes的唯一组合的重复startdates,这将会留下重复项。你还应该检查enddates是否总是有相应的startdates,因为你会失去差距 - 但这可能只是你想要的东西。

除了创建备份,您可能会在事务中包装更新/删除,在删除和回滚之后执行选择,然后检查Excel中的数据,如果一切正常,请重复此事务,但在此次提交。

更新:此查询识别差距。如果您在Sql Server 2000上,请将CTE转换为派生表。首先返回没有前辈的资源列表,最后对后继者也是如此。两者都计算差距。然后列表通过resNo,subRes和缺口编号进行连接。

;with first as (
    select resNo, subres, startdate, 
    row_number() over (partition by resNo, subres order by startdate) rowNumber 
     from t_resourcetable 
    where not exists (select null 
         from t_resourcetable t1 
         where t1.resNo = t_resourcetable.resNo 
         and t1.subres = t_resourcetable.subres 
         and t1.enddate = t_resourcetable.startdate) 
), 
last as (
    select resNo, subres, enddate, 
    row_number() over (partition by resNo, subres order by enddate) rowNumber 
    from t_resourcetable 
    where not exists (select null 
         from t_resourcetable t1 
         where t1.resNo = t_resourcetable.resNo 
         and t1.subres = t_resourcetable.subres 
         and t1.startdate = t_resourcetable.enddate) 
) 
select first.resno, first.subres, first.startdate, last.enddate 
from first 
    inner join last 
    on first.resNo = last.resNo 
    and first.subres = last.subres 
    and first.rowNumber = last.rowNumber 
+0

这将不会返回资源1和子资源2(从2012年1月1日开始)(2012年1月1日 - 2012年1月1日)/2012)。而这只会导致连续资源使用的一行(2/1/2012-16/1/2012)感谢您的回复nikola – 2012-03-27 09:42:43

+0

@ steavefinner我编辑了我的答案。 – 2012-03-27 10:45:42

+0

感谢尼科拉,但我相信这将是非常耗时的... – 2012-03-27 13:06:26

1

的你需要通过resNo和subRes来对你的数据进行分组:

select resNo, subRes, min(startdate), max(enddate) 
from t_resourcetable 
group by resNo, subRes 

并将结果插入临时表。

然后你就可以截断t_resourcetable并插入从临时tample的reult进去

+1

它不会工作,因为资源1的数据被使用两次,并且group by将只返回一行,其中resourceno(1)和subres(2) – 2012-03-27 09:13:11

+0

的实际结果应该有两行,它们按这两个字段分组: resNo,subRes – Diego 2012-03-27 09:19:31

+0

是的,它是通过将这两个字段分组resno,subres,通过分组创建两个diffe创建一个记录在不同的日期租用两次相同的资源。理想情况下它应该是两行 – 2012-03-27 09:22:06

0

你可以试试这个吗?

SELECT resno, 
     subres, 
     startdate, 
     MIN(enddate) AS enddate 
FROM (SELECT t1.resno, 
       t1.subres, 
       t1.startdate, 
       t2.enddate 
     FROM t_resourcetable t1, 
       t_resourcetable t2 
     WHERE t1.enddate <= t2.enddate 
       AND NOT EXISTS (SELECT * 
           FROM t_resourcetable t3 
           WHERE (t1.resno = t3.resno 
             AND t1.subres = t3.subres 
             AND t1.startdate > t3.startdate 
             AND t1.startdate <= t3.enddate) 
             OR (t2.resno = t3.resno 
              AND t2.subres = t3.subres 
              AND t2.enddate >= t3.startdate 
              AND t2.enddate < t3.enddate)))t 
GROUP BY resno, 
      subres, 
      startdate 

的图像是像

TimeLine