比较子选择中不同行的值

时间:2014-12-10 18:07:17

标签: sql sql-server-2008

我正在尝试撤回一些数据并遇到查询问题。

我有两张桌子:

联系

  • CONTACT_ID

注册

  • START_DATE
  • END_DATE
  • Owning_Contact_ID
  • PRODUCT_ID
  • Enrollment_ID

这是一对多关系,其中每个联系人都有0到N个注册。我想找到每个联系人的最新(就开始日期而言)两个注册,并且只有在enrollment1的开始日期(最新开始日期)和enrollment2的结束日期(第二个到最晚开始日期)之间的差异大于时才返回它们。 1天或者product_id在这两个注册范围之间是不同的。

我最初的想法是加入注册表的两个实例,但这很慢并需要很长时间。还有更好的方法吗?

查询:

 select * from contact CONT with (nolock)
            INNER JOIN Enrollment ENROLL1 with (nolock)
            on (ENROLL1.Enrollment_ID =
            (SELECT TOP 1 EN.Enrollment_ID FROM Enrollment EN WITH(NOLOCK) 
                where EN.Contact_id = CONT.Contact_Id
                                     order by EN.start_date desc)
            INNER JOIN Enrollment ENROLL2 with (nolock)
            on (ENROLL2.Enrollment_ID =
            (SELECT TOP 1 EN2.Enrollment_ID FROM Enrollment EN2 WITH(NOLOCK) 
                where EN2.Contact_id = CONT.Contact_Id
                                     order by EN2.start_date desc)
                             where Enroll1.Product_ID != Enroll2.Product_ID

(我从未开始处理日期差异位,因为我试图在添加之前先完成上述工作)。

2 个答案:

答案 0 :(得分:1)

您可以通过以下方式找到最近的2个注册:

select e.*
from (select e.*, row_number() over (partition by contact_id order by start_date desc) as seqnum
      from enrollment e
     ) e
where seqnum <= 2;

您可以使用条件聚合和having子句获取所需的摘要信息:

select contact_id
from (select e.*, row_number() over (partition by contact_id order by start_date desc) as seqnum
      from enrollment e
     ) e
where seqnum <= 2
group by contact_id
having min(productid) <> max(productid) or
       max(start_date) > dateadd(day, 1, min(start_date))

如果您想了解有关联系人的其他信息,可以加入其他表格。

要获得符合以下条件的最新两个注册:

select e.*
from (select e.*, row_number() over (partition by contact_id order by start_date desc) as seqnum
      from enrollment e
     ) e join
     (select contact_id
      from (select e.*, row_number() over (partition by contact_id order by start_date desc) as seqnum
            from enrollment e
           ) e
      where seqnum <= 2
      group by contact_id
      having min(productid) <> max(productid) or
             max(start_date) > dateadd(day, 1, min(start_date))
     ) ee
     on e.contact_id = ee.contact_id and e.seqnum <= 2;

答案 1 :(得分:0)

这样的东西?

SELECT *
FROM Contact CONT
CROSS APPLY (SELECT TOP 1 Enrollment.* FROM Enrollment WHERE Owning_Contact_ID = CONT.Contact_ID ORDER BY Start_date desc)

哪些列有索引?注册需要Owning_Contact_ID和Start_date的索引。