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
;