为子查询连接中的字段添加日期过滤(附现有聚合查询)
嘿,我明白你要给那些子查询加上日期过滤的需求了。你的现有聚合逻辑已经跑通,现在只需要针对每个子查询里的表添加日期条件就行,具体可以按下面的方式来实现:
实现方案
1. 在每个子查询内部添加日期过滤(最直接的业务匹配方式)
如果每个子查询对应的表(比如PS_GHS_HS_ANN_EXAM、以及你提到的H/J/M/P/S/V/Y表)都有自己的业务日期字段(比如体检日期EXAM_DATE、记录创建日期CREATE_DATE这类),你可以直接在每个子查询的WHERE子句里添加日期范围条件。这样只会统计符合日期要求的行,再参与后续的求和计算。
举个修改后的完整示例(以G表为例,其他子query依葫芦画瓢即可):
SELECT 'COUNTS', SUM(G.ROW_COUNT) + SUM(H.ROW_COUNT) + SUM(J.ROW_COUNT) + SUM(M.ROW_COUNT) + SUM(P.ROW_COUNT) + SUM(S.ROW_COUNT) + SUM(V.ROW_COUNT) + SUM(Y.ROW_COUNT) FROM PS_JOB F LEFT OUTER JOIN ( SELECT EMPLID, EMPL_RCD, COUNT(*) AS ROW_COUNT FROM PS_GHS_HS_ANN_EXAM G -- 这里添加日期过滤,比如筛选2023年全年的体检记录 WHERE G.EXAM_DATE >= '2023-01-01' AND G.EXAM_DATE < '2024-01-01' GROUP BY EMPLID, EMPL_RCD ) G ON F.EMPLID = G.EMPLID AND F.EMPL_RCD = G.EMPL_RCD -- 示例:H表的子查询添加日期过滤 LEFT OUTER JOIN ( SELECT EMPLID, EMPL_RCD, COUNT(*) AS ROW_COUNT FROM PS_XXX_H_TABLE H -- 假设H表用的是记录生效日期 WHERE H.EFFDT BETWEEN '2023-01-01' AND '2023-12-31' GROUP BY EMPLID, EMPL_RCD ) H ON F.EMPLID = H.EMPLID AND F.EMPL_RCD = H.EMPL_RCD -- 剩下的J/M/P/S/V/Y子查询都按同样逻辑添加WHERE日期条件即可
2. 基于主表PS_JOB的日期过滤(如果业务是聚焦特定时间段的员工)
如果你的需求是只统计主表PS_JOB中符合日期条件的员工对应的子表记录(比如只看2023年入职的员工的各类记录),那可以在主查询末尾添加WHERE条件,或者在子查询里关联主表的日期字段。比如假设PS_JOB有入职日期HIRE_DATE字段:
SELECT 'COUNTS', SUM(G.ROW_COUNT) + SUM(H.ROW_COUNT) + SUM(J.ROW_COUNT) + SUM(M.ROW_COUNT) + SUM(P.ROW_COUNT) + SUM(S.ROW_COUNT) + SUM(V.ROW_COUNT) + SUM(Y.ROW_COUNT) FROM PS_JOB F LEFT OUTER JOIN ( SELECT EMPLID, EMPL_RCD, COUNT(*) AS ROW_COUNT FROM PS_GHS_HS_ANN_EXAM G GROUP BY EMPLID, EMPL_RCD ) G ON F.EMPLID = G.EMPLID AND F.EMPL_RCD = G.EMPL_RCD -- 其他子查询省略... -- 过滤主表中2023年入职的员工 WHERE F.HIRE_DATE >= '2023-01-01' AND F.HIRE_DATE < '2024-01-01'
⚠️ 注意:这两种方式的业务逻辑完全不同,第一种是子表自身的业务日期过滤,第二种是主表员工的属性日期过滤,一定要根据你的实际业务需求选择!
3. 小技巧:统一日期变量提升维护性
如果所有子查询的日期范围是统一的,建议用变量来定义日期值,避免重复写相同的日期字符串,后续修改也更方便。不同数据库的变量语法略有不同,举两个常见例子:
SQL Server 示例
DECLARE @StartDate DATE = '2023-01-01'; DECLARE @EndDate DATE = '2023-12-31'; SELECT 'COUNTS', SUM(G.ROW_COUNT) + SUM(H.ROW_COUNT) + ... FROM PS_JOB F LEFT OUTER JOIN ( SELECT EMPLID, EMPL_RCD, COUNT(*) AS ROW_COUNT FROM PS_GHS_HS_ANN_EXAM G WHERE G.EXAM_DATE BETWEEN @StartDate AND @EndDate GROUP BY EMPLID, EMPL_RCD ) G ON F.EMPLID = G.EMPLID AND F.EMPL_RCD = G.EMPL_RCD -- 其他子查询直接复用@StartDate和@EndDate即可
Oracle 示例
DEFINE StartDate = '2023-01-01'; DEFINE EndDate = '2023-12-31'; SELECT 'COUNTS', SUM(G.ROW_COUNT) + SUM(H.ROW_COUNT) + ... FROM PS_JOB F LEFT OUTER JOIN ( SELECT EMPLID, EMPL_RCD, COUNT(*) AS ROW_COUNT FROM PS_GHS_HS_ANN_EXAM G WHERE G.EXAM_DATE BETWEEN TO_DATE('&StartDate', 'YYYY-MM-DD') AND TO_DATE('&EndDate', 'YYYY-MM-DD') GROUP BY EMPLID, EMPL_RCD ) G ON F.EMPLID = G.EMPLID AND F.EMPL_RCD = G.EMPL_RCD
性能优化提示
- 给每个子查询表的日期字段(比如
EXAM_DATE、EFFDT)创建索引,这样日期过滤的查询速度会大幅提升,尤其是数据量较大的场景。 - 如果子查询的过滤条件和分组字段匹配,考虑创建复合索引(比如
(EMPLID, EMPL_RCD, EXAM_DATE)),进一步优化分组和过滤的效率。
内容的提问来源于stack exchange,提问作者JBinson88




