t-sql中的CTE公共表exp

t-sql中的CTE公共表exp,sql,tsql,common-table-expression,Sql,Tsql,Common Table Expression,我对以下查询有问题: WITH CTE_1 (stu_id ,meet_doc_id ,doc_name ,stu_name ,dob ,done ,date_meet_doc) AS (SELECT stu_id ,meet_doc_id ,doc_name ,stu_name ,dob

我对以下查询有问题:

WITH CTE_1 (stu_id
            ,meet_doc_id
            ,doc_name
            ,stu_name
            ,dob
            ,done
            ,date_meet_doc)
AS

(SELECT stu_id
        ,meet_doc_id
        ,doc_name
        ,stu_name
        ,dob
        ,CASE
              WHEN (PATINDEX('%SMOKING%',act.VALUE)) THEN 
                           'LMDO'                       
              WHEN (PATINDEX('%NOT SMOKING%',act.VALUE)) THEN  
                            'LMD1'                       
              WHEN (ISNULL(CAST(act.VALUE as varchar(max)),'')='') THEN     
                            'CLEAR'                       
              ELSE                                   
                            'CLEAR'    
              END done 
        ,date_meet_doc

FROM 
abc INNER JOIN
INNER JOIN 
INNER JOIN 
WHERE multiple conditions
)

SELECT * FROM CTE_1 one
WHERE date =(SELECT MAX(DATE) FROM CTE_1 two WHERE two.stu_id=one.stu_id
AND one.doc_name=two.doc_name)
ORDER BY stu_name,dob
;
三个学生(例如)的内部查询(CTE_1)的结果集如下

stu_id   meet_doc_id   doc_name   stu_name      dob        value      date
101        0104          AD          AM      15/06/1950     LMDO     2011-02-15
101        0105          AD          AM      15/06/1950     CLEAR    2011-02-18
101        0106          AD          AM      15/06/1950     CLEAR    2011-02-25
102        0107          AD          AK      12/08/1987     CLEAR    2011-03-28
102        0108          AD          AK      12/08/1987     LDMO     2011-04-29
103        0109          PK          LMP     13/07/1970     CLEAR    2011-03-28
103        0110          PK          LMP     13/07/1970     CLEAR    2011-05-12
当我执行整个查询时,我的结果集将是

stu_id   meet_doc_id   doc_name   stu_name      dob         value      date
101        0106          AD          AM      15/06/1950     CLEAR    2011-02-25
102        0108          AD          AK      12/19/1987     LDMO     2011-04-29
103        0110          PK          LMP     13/07/1970     CLEAR    2011-05-12
如何更改外部查询以仅为特定学生选择那些值,即LDMO或LMD1,并且其医生相同?

假设如果学生多次遇到doc,并且在任何情况下,如果学生获得LMDO或LMD1,则无论日期如何,只应选择该记录

我希望我的结果集类似于:

stu_id   meet_doc_id   doc_name   stu_name      dob         value      date
101        0104          AD          AM      15/06/1950     LMDO     2011-02-15
102        0107          AD          AK      12/08/1987     CLEAR    2011-03-28
103        0110          PK          LMP     13/07/1970     CLEAR    2011-05-12
其背后的逻辑是,如果stu_id相同,doc_名称相同,并且如果存在一个值LMDO或LMD1,则显示该记录,如果不显示已清除的记录。
我只想删除MAX(date)并为具有相同文档名的特定stu_id的整个报告期设置一个条件。

编辑:添加对我所做工作的高级描述

您希望通过两个可能的条件筛选原始信息(CTE_1)。最简单的方法是首先在他们自己的结果集中建立这些标准。因此,我们有一个子查询,它返回一个
(Student、Doc、Max(Date))
组合列表,以及一个在
LMDO/LMD1
值上过滤的类似列表

现在,我们需要将左连接到过滤后的数据,因为每个学生可能没有结果

现在您有了一个
Student/Doc/MaxDate
列表,还有一个可能的
FilteredDate

最后一步是将结果集
连接到原始数据(CTE_1)。由于FilteredDate优先,我们首先通过
ISNULL
函数检查它,如果它不存在,则使用MaxDate


首先,我将原始查询更改为以下内容,因为我认为通过消除相关子查询,您将看到在大型数据集上的一些性能提高:

SELECT * 
FROM CTE_1 one
INNER JOIN 
  (SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1 group by stu_id,doc_name) two
  ON one.stu_id = two.stu_id and one.doc_name = two.doc_name
ORDER BY stu_name,dob
现在,我们可以添加一个额外的、类似的join,以获取值位于所需列表中的max(date)。我们还需要将连接移动一点

SELECT realdata.* 
FROM 
  ((SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1 group by stu_id,doc_name) maxdt
LEFT JOIN 
  (SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1 
   WHERE value in ('LMDO', 'LMD1')
   group by stu_id,doc_name) filtered
  ON maxdt.stu_id = filtered.stu_id and maxdt.doc_name = filtered.doc_name)
INNER JOIN CTE_1 realdata
  ON realdata.stu_id = maxdt.stu_id and realdata.doc_name = maxdt.doc_name
     and realdata.date = isnull(filtered.maxdate, maxdt.maxdate)
ORDER BY realdata.stu_name,realdata.dob
感谢那些试图理解但由于我无法解释而放弃的人。
再次感谢各位:)

非常感谢,德里克,至少你没有放弃,因为你试图理解我的塞纳里奥。下面是我的答案。再次感谢:)
declare @TestTable
as table
(stu_id int,
 meet_doc_id  char(4), 
 doc_name  char(2), 
 stu_name  varchar(3),   
 dob date,
 value  varchar(5),
 date_meet_doc date)

insert into @TestTable
(stu_id,meet_doc_id,doc_name,stu_name,dob,value,date_meet_doc)
values
(101,'0104','AD','AM', '19500615','LDMO' ,'2011-02-15'),
(101,'0105','AD','AM', '19500615','CLEAR','2011-02-18'),
(101,'0106','AD','AM', '19500615','CLEAR','2011-02-25'),
(102,'0107','AD','AK', '19870812','CLEAR','2011-03-28'),
(102,'0108','AD','AK', '19870812','LDMO' ,'2011-04-29'),
(103,'0109','PK','LMP','19700713','CLEAR','2011-03-28'),
(103,'0110','PK','LMP','19700713','CLEAR','2011-05-12');

WITH CTE_1 (stu_id
                ,meet_doc_id
                ,doc_name
                ,stu_name
                ,dob
                ,done
                ,date_meet_doc)
    AS

    (SELECT stu_id
            ,meet_doc_id
            ,doc_name
            ,stu_name
            ,dob
            ,value
            ,date_meet_doc

    FROM @TestTable
    ),
    CTE_2 as(
    SELECT *,row_number() over (partition by stu_id order by  case when done in ('LDMO','LDM1') then 0 else 1 end, date_meet_doc desc) rn FROM CTE_1) 
    select stu_id
            ,meet_doc_id
            ,doc_name
            ,stu_name
            ,dob
            ,value
            ,date_meet_doc
    from CTE_2 where rn=1
    ;