SQL在X天内查找下一个后续操作(连接比较日期时间)
我正在尝试编写一个查询,从一个时间表表中提取日期,并查看他们是否在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 '
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
子句中。我想这个也行。我正在用真实数据测试它,但可能只有我。对于某些行,它是在我预约之前接电话的日期。在这种情况下,你能编一把小提琴吗?我不知道这怎么可能。我认为这个也行。我正在用真实数据测试它,但可能只有我。对于某些行,它是在我预约之前接电话的日期。在这种情况下,你能编一把小提琴吗?我不知道这怎么可能。我喜欢所有这些答案,因为它们都可能使用不同的策略。是的,这是阅读材料!谢谢,我喜欢所有这些答案,因为它们都可能使用不同的策略。是的,这是阅读材料!谢谢