2011-08-30 80 views
0

我有以下查询一个问题:CTE-公共表EXP

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的整个报告周期设置一个条件。

回答

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 
    ; 

感谢那些谁试图了解,但放弃了,因为我不能解释它。 再次感谢你们:)

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 
+0

非常感谢,德里克atlest你没有放弃,因为试图进入我的senario。下面是为我制定的答案。再次感谢 :) – palum