SQL查找条件不存在的最新日期

SQL查找条件不存在的最新日期,sql,sql-server,Sql,Sql Server,我对SQL非常陌生,并且正在处理一个已经彻底击败我一段时间的查询。我经常来这个网站——这是一个非常好的资源,多亏了你的专业知识,通常我会找到我需要的东西,但这次我觉得我的查询有点太具体了,我没有找到合适的东西。谁能帮我一下吗 我有两个表:一个客户表和一个联系人表。我需要找到的是所有客户在某个日期之前的最近约会日,在本例中为“2015年8月11日”,该日任何约会的结果都不是“2”。每个客户在同一天可能有多个约会,其中任何一个约会的结果为“2”,这意味着我们必须忽略整个一天,并返回到最近的下一天 例

我对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”的相同日期,因为同一天的其他约会有另一个结果。我一直在试着玩我的桌子和分组游戏,但我并不存在,但我似乎没有取得任何进展

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