基于日期的查询验证:药房就诊客户项目匹配SQL逻辑确认
需求与SQL逻辑分析
首先明确你的核心需求:验证2017年有药房就诊记录的客户,是否仅参与了ProgramCode为1或2的项目,且每条就诊日期都落在对应项目的有效期(StartDate到EndDate)内。
当前SQL的正确性
你现在使用的SQL逻辑是符合核心需求中“就诊日期处于对应项目有效期内”这部分的,我对日期比较部分做了一点优化(去掉不必要的字符串转换,更高效严谨):
SELECT rx.LastName ,rx.FirstName ,rx.SSN ,rx.DateOfService ,cp1.Description ,cp.startDate ,cp.endDate FROM pharmacy rx INNER JOIN client c ON REPLACE(c.SSN,'-','') = rx.SSN INNER JOIN client_program cp ON cp.ClientID = c.ClientID INNER JOIN program_code cp1 ON cp1.ProgramCode = cp.ProgramCode WHERE rx.DateOfService >= '2017-01-01' AND rx.DateOfService < '2018-01-01' -- 比BETWEEN更严谨,避免datetime类型的时间部分干扰 AND cp.ProgramCode IN ('1', '2') AND rx.DateOfService BETWEEN cp.StartDate AND cp.EndDate
这条SQL的逻辑链很清晰:
- 先筛选2017年全年的药房就诊记录
- 关联到对应客户,再关联到客户参与的1/2类项目
- 最后确保这条就诊的日期确实落在该项目的有效期内
完全匹配你需要验证的“就诊日期处于所参与项目的起止日期范围内”的要求。
为什么之前的条件返回更多记录?
你之前尝试的条件:
AND (convert(char(10),cp.EndDate,120) BETWEEN '2017-01-01' AND '2017-12-31' OR convert(char(10),cp.StartDate,120) BETWEEN '2017-01-01' AND '2017-12-31')
这个条件的问题在于:它只是筛选项目的有效期和2017年有重叠,但没有把就诊日期和项目有效期做绑定。举个实际例子:
- 客户Judy的项目3(ProgramCode=2)是2017-11-08开始,2018-11-08结束
- 她在2017-11-01有一条就诊记录,这个日期早于项目3的StartDate
- 但用之前的条件,因为项目3的StartDate在2017年内,这条就诊记录会被错误关联到项目3,而实际上就诊时客户还没参与这个项目
这就是为什么之前的条件返回更多记录——它包含了不符合“就诊日期在项目有效期内”的错误匹配。
补充:验证客户是否仅参与1/2项目
当前的SQL只能筛选出客户参与的1/2项目且就诊日期符合的记录,但如果客户同时参与了3/4类项目,这条SQL无法帮你发现。如果要完成“客户是否仅参与1/2项目”的验证,可以用以下查询:
-- 找出2017年有就诊记录,但同时参与了非1/2项目的客户(用于排查不符合要求的情况) SELECT DISTINCT c.ClientID, c.LastName, c.FirstName, c.SSN FROM client c INNER JOIN pharmacy rx ON REPLACE(c.SSN,'-','') = rx.SSN INNER JOIN client_program cp ON cp.ClientID = c.ClientID WHERE rx.DateOfService >= '2017-01-01' AND rx.DateOfService < '2018-01-01' AND cp.ProgramCode NOT IN ('1','2') -- 找出2017年有就诊记录且仅参与1/2项目的客户(用于确认符合要求的情况) SELECT c.ClientID, c.LastName, c.FirstName, c.SSN FROM client c INNER JOIN pharmacy rx ON REPLACE(c.SSN,'-','') = rx.SSN WHERE rx.DateOfService >= '2017-01-01' AND rx.DateOfService < '2018-01-01' AND NOT EXISTS ( SELECT 1 FROM client_program cp WHERE cp.ClientID = c.ClientID AND cp.ProgramCode NOT IN ('1','2') ) GROUP BY c.ClientID, c.LastName, c.FirstName, c.SSN
内容的提问来源于stack exchange,提问作者DataCrypt
相关产品推荐
相关产品推荐

