CT-common表格在t-sql中

时间:2011-08-30 19:47:34

标签: 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
        ,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以及哪位医生相同?

假设学生多次符合该文件,并且如果在任何情况下,如果学生获得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_name相同,并且如果存在LMDO或LMD1的值,则显示该记录,如果不显示具有CLEAR的记录。     我只想删除MAX(日期),并为具有相同doc_name的特定stu_id的整个报告周期设置一个条件。

2 个答案:

答案 0 :(得分:1)

修改:添加我所做的高级描述。

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

现在,我们需要LEFT JOIN来过滤数据,因为每个学生可能没有结果。

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

最后一步是将JOIN结果集设置为原始数据(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

现在,我们可以添加一个额外的类似联接,以获取值在所需列表中的最大值(日期)。我们还需要稍微改变连接。

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

答案 1 :(得分:1)

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
    ;

感谢那些试图理解但放弃的人,因为我无法解释它。 再次感谢你们:)

相关问题