SQL查找条件不存在的最新日期
我对SQL非常陌生,并且正在处理一个已经彻底击败我一段时间的查询。我经常来这个网站——这是一个非常好的资源,多亏了你的专业知识,通常我会找到我需要的东西,但这次我觉得我的查询有点太具体了,我没有找到合适的东西。谁能帮我一下吗 我有两个表:一个客户表和一个联系人表。我需要找到的是所有客户在某个日期之前的最近约会日,在本例中为“2015年8月11日”,该日任何约会的结果都不是“2”。每个客户在同一天可能有多个约会,其中任何一个约会的结果为“2”,这意味着我们必须忽略整个一天,并返回到最近的下一天 例如,客户“3”的返回约会日期应为“2015年7月1日”,而“2015年7月16日”的返回约会日期仅为一行,而不是两行,因为“2015年7月16日”的其中一个约会的结果为“2”。结果的所有其他值都是可接受的,包括NULL,而不是“2” 同一天的多个约会位是我发现的棘手部分-我可以使用Select MAX或TOP 1语句查找最新的约会日期,但当我添加“2”时,它仍然会继续返回可能有结果“2”的相同日期,因为同一天的其他约会有另一个结果。我一直在试着玩我的桌子和分组游戏,但我并不存在,但我似乎没有取得任何进展SQL查找条件不存在的最新日期,sql,sql-server,Sql,Sql Server,我对SQL非常陌生,并且正在处理一个已经彻底击败我一段时间的查询。我经常来这个网站——这是一个非常好的资源,多亏了你的专业知识,通常我会找到我需要的东西,但这次我觉得我的查询有点太具体了,我没有找到合适的东西。谁能帮我一下吗 我有两个表:一个客户表和一个联系人表。我需要找到的是所有客户在某个日期之前的最近约会日,在本例中为“2015年8月11日”,该日任何约会的结果都不是“2”。每个客户在同一天可能有多个约会,其中任何一个约会的结果为“2”,这意味着我们必须忽略整个一天,并返回到最近的下一天 例
Contact
ClientID AppDate Outcome
1 30/07/2015 17:00 2
1 01/07/2015 17:00 3
2 03/03/2015 16:00 NULL
2 01/03/2015 16:00 NULL
3 16/07/2015 15:40 6
3 16/07/2015 15:40 2
3 01/07/2015 15:40 3
4 05/08/2015 12:30 6
4 05/08/2015 12:30 2
4 01/08/2015 12:30 3
5 23/07/2015 15:30 2
5 23/07/2015 15:30 NULL
5 01/07/2015 15:30 4
6 20/07/2015 10:10 NULL
6 20/07/2015 10:10 2
6 01/07/2015 10:10 6
7 23/07/2015 15:40 2
7 01/07/2015 15:40 1
7 23/06/2015 15:40 8
8 13/07/2015 11:30 2
8 13/07/2015 11:30 6
8 01/07/2015 11:30 2
8 01/06/2015 11:30 3
9 29/07/2015 17:00 3
9 29/07/2015 17:00 6
10 14/07/2015 11:00 NULL
10 01/07/2015 11:00 5
Client
ClientID Forename Surname
1 I B
2 J B
3 S C
4 S T
5 P C
6 K D
7 P E
8 P H
9 S F
10 A G
如果我错过了一些显而易见的东西,我道歉!感谢您的阅读和回复。我附上我的截短查询,供您一般娱乐
SELECT
cli.ClientID ,
cli.Forename ,
cli.Surname ,
con.AppDate ,
con.Outcome
FROM
Client AS cli
INNER JOIN
Contact AS con
ON cli.ClientID = con.ClientID
AND con.AppDate =
(SELECT MAX(con1.AppDate)
FROM Contact AS con1
WHERE con.ClientID = con1.ClientID
AND con1.AppDate < '11/08/2015 00:00:00'
AND con1.Outcome <> '2')
ORDER BY
cli.ClientID
你需要做的是有一个条件,挑选出结果为两个的所有日期并过滤掉 大概是这样的:
WITH ClientCTE AS
(
SELECT MAX(con1.AppDate) AS AppDate ,ClientID
FROM Contact AS con1
WHERE con.ClientID = con1.ClientID
AND con1.AppDate < '11/08/2015 00:00:00'
AND con1.Outcome <> '2'
AND con1.AppDate NOT IN (SELECT AppDate FROM Contact WHERE Outcome = '2'))
SELECT
* FROM Client C
INNER JOIN
Contact AS con
ON cli.ClientID = con.ClientID
INNER JOIN ClientCTE CTE
ON cli.ClientID = CTE.ClientCTE
AND CTE.AppDate = con.AppDate
让我知道它是否有效我认为交叉应用是最好的方法:
select c.*, con.*
from client c cross apply
(select top 1 con.*
from (select con.*,
sum(case when Outcome = 2 then 1 else 0 end) over (partition by ClientId, AppDate) as num2s
from contact con
where con.ClientId = c.ClientId and
con.AppDate < '2015-11-08'
) con
where num2s = 0
order by AppDate desc
) con;
在本例中,交叉应用的工作方式非常类似于相关子查询,但您可以返回多个值。子查询使用窗口函数计算给定日期的2个数,其余逻辑应该非常明显
这将从最近的日期返回一行,其中包含相应的约会。如果需要多个这样的行,请使用with ties。请尝试以下查询。 它使用MAXcase。。。按CASTAppDate作为日期窗口进行分区的函数,用于标记在同一天有2个结果的所有约会,以及筛选日期的WHERE子句。 然后,在外部WHERE子句中使用此标志来删除不需要的数据,并在联系人和客户机表上联接
SELECT
cli.ClientID ,
cli.Forename ,
cli.Surname ,
con.AppDate ,
con.Outcome
from
client cli right join contact con
on con.ClientID=cli.ClientID
inner join
(
select ClientID,MAX(AppDate)as lastDate from
( select *,
MAX(CASE when ISNULL(Outcome,1) =2 then 1 else 0 end) OVER(PARTITION BY CAST(AppDate as DATE),ClientID ORDER BY AppDate) as flag
from Contact
where AppDate< '2015-11-08'
) p
where flag =0 group by ClientID
) s
on s.ClientId=con.ClientID and s.lastDate=con.AppDate
这里还有到sql FIDLE的演示链接:
这个问题不清楚,您能提供表中的预期输出吗?这个问题缺少的是预期结果W,这正是我想要的。非常感谢你!
SELECT
cli.ClientID ,
cli.Forename ,
cli.Surname ,
con.AppDate ,
con.Outcome
from
client cli right join contact con
on con.ClientID=cli.ClientID
inner join
(
select ClientID,MAX(AppDate)as lastDate from
( select *,
MAX(CASE when ISNULL(Outcome,1) =2 then 1 else 0 end) OVER(PARTITION BY CAST(AppDate as DATE),ClientID ORDER BY AppDate) as flag
from Contact
where AppDate< '2015-11-08'
) p
where flag =0 group by ClientID
) s
on s.ClientId=con.ClientID and s.lastDate=con.AppDate