SQL在X天内查找下一个后续操作(连接比较日期时间)

SQL在X天内查找下一个后续操作(连接比较日期时间),sql,sql-server,join,next,Sql,Sql Server,Join,Next,我正在尝试编写一个查询,从一个时间表表中提取日期,并查看他们是否在X天内有来自另一个表的后续联系人 我有一个类似这样的查询,但它没有正确地进行检查。我的逻辑在我脑海中似乎是正确的,但我想这是不对的: select appointments.person_id ,appointments.date ,nextDate.minDate ,case when datediff(d,appointments.date,nextdate.minDate) <= 3 then 'yes' else '

我正在尝试编写一个查询,从一个时间表表中提取日期,并查看他们是否在X天内有来自另一个表的后续联系人

我有一个类似这样的查询,但它没有正确地进行检查。我的逻辑在我脑海中似乎是正确的,但我想这是不对的:

select
appointments.person_id
,appointments.date
,nextDate.minDate
,case when datediff(d,appointments.date,nextdate.minDate) <= 3 then 'yes' else 'no' end as 'within3days'

from appointments
left join
(
select person_id, min(date) as minDate
from calls
group by person_id
) as nextDate on appointments.person_id = nextDate.person_id and appointments.date <= nextDate.mindate
选择
预约.个人识别码
,约会日期
,nextDate.minDate

,datediff(d,appoints.date,nextdate.minDate)时的大小写我建议您为此使用
apply
。我认为这是表达你的逻辑最简单的方式:

select a.person_id, a.datetime, c.datetime as nextdatetime,
       (case when datediff(d, a.datetime, c.datetime) <= 3 then 'yes' else 'no'
        end) as within3days
from appointments a outer apply
     (select top 1 c.*
      from calls c
      where c.person_id = a.person_id and
            c.datetime > a.datetime
      order by c.datetime
     ) c;
选择a.person\u id、a.datetime、c.datetime作为nextdatetime,
(datediff(d,a.datetime,c.datetime)a.datetime时的大小写
按c.datetime订购
)c;

我建议您为此使用
apply
。我认为这是表达你的逻辑最简单的方式:

select a.person_id, a.datetime, c.datetime as nextdatetime,
       (case when datediff(d, a.datetime, c.datetime) <= 3 then 'yes' else 'no'
        end) as within3days
from appointments a outer apply
     (select top 1 c.*
      from calls c
      where c.person_id = a.person_id and
            c.datetime > a.datetime
      order by c.datetime
     ) c;
选择a.person\u id、a.datetime、c.datetime作为nextdatetime,
(datediff(d,a.datetime,c.datetime)a.datetime时的大小写
按c.datetime订购
)c;

我想这就是你想要的:

select a.person_id,
       a.date,
       c.date as first_call_after,
       case when datediff(d,a.date,c.date) >= 3
            then 'yes' else 'no' end as within3days
  from appointments a
  left join calls c
    on a.person_id = c.person_id
   and c.date = (select min(x.date)
                   from calls x
                  where x.person_id = c.person_id
                    and x.date >= a.date)
 order by a.person_id, a.date
小提琴:

您正在加入此人的第一个电话,任何电话。您真正想要的是在指定行的约会之后进行的第一次呼叫。


编辑,只是将x.date>a.date更改为x.date>=a.date,以防某人在约会后立即拨打电话。在我的上述陈述中,我应该说“发生在……或之后”

我想这就是你想要的:

select a.person_id,
       a.date,
       c.date as first_call_after,
       case when datediff(d,a.date,c.date) >= 3
            then 'yes' else 'no' end as within3days
  from appointments a
  left join calls c
    on a.person_id = c.person_id
   and c.date = (select min(x.date)
                   from calls x
                  where x.person_id = c.person_id
                    and x.date >= a.date)
 order by a.person_id, a.date
小提琴:

您正在加入此人的第一个电话,任何电话。您真正想要的是在指定行的约会之后进行的第一次呼叫。

编辑,只是将x.date>a.date更改为x.date>=a.date,以防某人在约会后立即拨打电话。在我上面的陈述中,我应该说“发生在……或之后”

我“认为”这基本上就是你想要做的。使用窗口功能将数据分区,可以构建这种类型的逻辑。您必须查看并调整它以获得所需内容,但您应该能够看到如何按一个或多个列进行分区,然后使用“between”子句选择行集

这种逻辑通常用于构建移动平均线,因此我还提供了一个代码示例,供您阅读。对我来说,windowing函数更清楚地说明了问题所在,但习惯语法需要几分钟

select [appointments].[visit_id]            as [visit_id]
   , [appointments].[person_id]         as [person_id]
   , [appointments].[date]              as [appointment_date]
   , [calls].[call_id]                  as [call_id]
   , [calls].[date]                     as [call_date]
   , min([calls].[date])
       over (
         partition by [appointments].[person_id]
         order by [calls].[date] desc
       rows between current row and 3 following ) as [minimum_date]
from   [dbo].[appointments] as [appointments]
   join [dbo].[calls] as [calls]
     on [calls].[person_id] = [appointments].[person_id]; 


with [average_builder] as (
select [symbol], [date],[close],[0003_day_ave],
avg([close])
over (
    partition by [symbol]
    order by [date] desc
    rows between current row and 2 following
) as [average]
from  [equity].[data]
where [0003_day_ave] is null)
update [average_builder] set [0003_day_ave] = [average];
我“认为”这基本上就是你想要做的。使用窗口功能将数据分区,可以构建这种类型的逻辑。您必须查看并调整它以获得所需内容,但您应该能够看到如何按一个或多个列进行分区,然后使用“between”子句选择行集

这种逻辑通常用于构建移动平均线,因此我还提供了一个代码示例,供您阅读。对我来说,windowing函数更清楚地说明了问题所在,但习惯语法需要几分钟

select [appointments].[visit_id]            as [visit_id]
   , [appointments].[person_id]         as [person_id]
   , [appointments].[date]              as [appointment_date]
   , [calls].[call_id]                  as [call_id]
   , [calls].[date]                     as [call_date]
   , min([calls].[date])
       over (
         partition by [appointments].[person_id]
         order by [calls].[date] desc
       rows between current row and 3 following ) as [minimum_date]
from   [dbo].[appointments] as [appointments]
   join [dbo].[calls] as [calls]
     on [calls].[person_id] = [appointments].[person_id]; 


with [average_builder] as (
select [symbol], [date],[close],[0003_day_ave],
avg([close])
over (
    partition by [symbol]
    order by [date] desc
    rows between current row and 2 following
) as [average]
from  [equity].[data]
where [0003_day_ave] is null)
update [average_builder] set [0003_day_ave] = [average];


你能提供一些样本数据吗?这看起来一点也不像是将预约联系在一起以确定后续预约。我假设同一个人可以有两次预约,其中第二次不一定是第一次的后续?SQL Server还支持分析函数,因此无论您最终使用什么查询,都可能涉及滞后函数。正确。几分钟后我会拉小提琴。感谢您的旁注:使用
datetime
作为列名可能不是一个好主意,因为它是数据类型的名称。您的左join@jpw yes中缺少
group by person\u id
。我正在写一些伪代码你能提供一些样本数据吗?这看起来一点也不像是将预约联系在一起以确定后续预约。我假设同一个人可以有两次预约,其中第二次不一定是第一次的后续?SQL Server还支持分析函数,因此无论您最终使用什么查询,都可能涉及滞后函数。正确。几分钟后我会拉小提琴。感谢您的旁注:使用
datetime
作为列名可能不是一个好主意,因为它是数据类型的名称。您的左join@jpw yes中缺少
group by person\u id
。我只是在写一些伪代码我想是它干的。我需要仔细看看这个,让它沉进去。我以前从未用过外敷。谢谢@jawz101。我不知道它是否有用,但在本例中,
outerapply
非常类似于一个相关子查询。除了,你可以把它放在
from
子句中。我想是这样的。我需要仔细看看这个,让它沉进去。我以前从未用过外敷。谢谢@jawz101。我不知道它是否有用,但在本例中,
outerapply
非常类似于一个相关子查询。除此之外,你可以把它放在
from
子句中。我想这个也行。我正在用真实数据测试它,但可能只有我。对于某些行,它是在我预约之前接电话的日期。在这种情况下,你能编一把小提琴吗?我不知道这怎么可能。我认为这个也行。我正在用真实数据测试它,但可能只有我。对于某些行,它是在我预约之前接电话的日期。在这种情况下,你能编一把小提琴吗?我不知道这怎么可能。我喜欢所有这些答案,因为它们都可能使用不同的策略。是的,这是阅读材料!谢谢,我喜欢所有这些答案,因为它们都可能使用不同的策略。是的,这是阅读材料!谢谢