我遇到以下问题的问题:
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的整个报告周期设置一个条件。
答案 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
;
感谢那些试图理解但放弃的人,因为我无法解释它。 再次感谢你们:)