【发布时间】:2014-12-12 20:54:22
【问题描述】:
我有一个场景,我需要从我的起始表 account_tbl 加入到 stu_ssn_tbl。我加入的列是stu_no 和stu_seq_no。
这是 stu_ssn_tbl 的结构
CREATE TABLE stu_ssn_tbl
(
curr_ssn_ind character(1),
no character(9),
pseudo_ssn_ind character(1),
src character(8),
stu_dob date,
stu_no integer ,
stu_seq_no integer,
sys_cr_dt date,
do_not_use character(1)
);
这是我的示例数据:
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','100 ','R','234600 ',to_timestamp('29-DEC-50','DD-MON-RR HH.MI.SSXFF AM'),1,7,to_timestamp('14-AUG-12','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','101','R','234600 ',to_timestamp('29-DEC-50','DD-MON-RR HH.MI.SSXFF AM'),1,7,to_timestamp('14-AUG-12','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','102 ','R','713001 ',to_timestamp('11-JAN-00','DD-MON-RR HH.MI.SSXFF AM'),1,6,to_timestamp('14-APR-03','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','203 ','R','368700 ',to_timestamp('05-DEC-53','DD-MON-RR HH.MI.SSXFF AM'),2,3,to_timestamp('01-JUL-98','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','104 ','R','368700 ',to_timestamp('05-DEC-53','DD-MON-RR HH.MI.SSXFF AM'),2,3,to_timestamp('01-JUL-98','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','105 ','P','341100 ',to_timestamp('20-JUL-43','DD-MON-RR HH.MI.SSXFF AM'),46,3,to_timestamp('11-FEB-13','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','106','P','341100 ',to_timestamp('20-JUL-43','DD-MON-RR HH.MI.SSXFF AM'),46,3,to_timestamp('11-FEB-13','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','107 ','R','184300 ',to_timestamp('27-JAN-55','DD-MON-RR HH.MI.SSXFF AM'),3,2,to_timestamp('22-MAY-01','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','108','R','184300 ',to_timestamp('27-JAN-55','DD-MON-RR HH.MI.SSXFF AM'),3,2,to_timestamp('22-MAY-01','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','109 ','R','368700 ',to_timestamp('27-NOV-61','DD-MON-RR HH.MI.SSXFF AM'),1,3,to_timestamp('01-JUL-98','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','601 ','R','368700 ',to_timestamp('27-NOV-61','DD-MON-RR HH.MI.SSXFF AM'),1,3,to_timestamp('01-JUL-98','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','900 ','R','293900 ',to_timestamp('20-JUN-71','DD-MON-RR HH.MI.SSXFF AM'),1,5,to_timestamp('23-APR-02','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('Y','2449','R','293900 ',to_timestamp('20-JUN-71','DD-MON-RR HH.MI.SSXFF AM'),1,5,to_timestamp('09-APR-03','DD-MON-RR HH.MI.SSXFF AM'),null);
Insert into stu_ssn_tbl (CURR_SSN_IND,NO,PSEUDO_SSN_IND,SRC,STU_DOB,STU_NO,STU_SEQ_NO,SYS_CR_DT,DO_NOT_USE) values ('N','95','P','293900 ',to_timestamp('20-JUN-71','DD-MON-RR HH.MI.SSXFF AM'),1,5,to_timestamp('23-APR-02','DD-MON-RR HH.MI.SSXFF AM'),null);
为简单起见,我们称这是account 表的结构。
CREATE TABLE account_tbl
(
id integer,
stu_no integer,
stu_seq_no integer
);
所以我要在 stu_no 和 stu_seq_no 上从 account 转到 stu_ssn_tbl
SELECT *
FROM ACCOUNT_TBL ACCT
LEFT OUTER JOIN STU_SSN_TBL SSN
ON ACCT.STU_NO = SSN.STU_NO
AND ACCT.STU_SEQ_NO = SSN.STU_SEQ_NO;
问题在于,这些表中的任何一个都没有强制唯一性(这些表是从没人知道的旧数据库中转储的数据)。我需要一种方法来根据以下规则从 stu_ssn_tbl 中选择正确的记录。
- SYS_CR_DT 最接近 ROLLUPDATE 的日期(将提供的日期,无需重复)。为了测试用例,我们可以说'2012-12-12'
- 如果存在两个或多个相同的 SYS_CR_DT 日期,请选择 CURR_SSN_IND = 'Y' 的记录。
- 如果无法根据 CURR_SSN_IND = 'Y' 选择记录(如果它们都是 'Y' 或 'N'),请选择 PSEUDO_SSN_IND = 'R' 的记录
- 如果仍然无法选择匹配,请随机选择记录。
我没有要求使用 PL/SQL 或常规 SQL 来完成此操作,只需要记住我正在处理 account_tbl 中的超过 3 亿条记录和接近 1 亿条记录stu_ssn_tbl。
对此我有两种想法。最好的方法是在 account_tbl 和 stu_ssn_tbl 之间的连接期间。但是,如果这是不可能的,我添加了 do_not_use 列,它可用于在功能上删除我不希望在预处理中的记录。
到目前为止,我有这个 - 这有助于我解决第 1 个问题,我决定通过 desc 订购 CURR_SSN_IND 和 PSEUDO_SSN_IND 的订单,因为它会给我在顶部观看的记录。我尝试在其上放置前 1 行,但这为整个表带回了 1 条记录。
SELECT
SRC.*
FROM STU_SSN_TBL SRC
LEFT OUTER JOIN STU_SSN_TBL CHK
ON SRC.STU_NO = CHK.STU_NO AND SRC.STU_SEQ_NO = CHK.STU_SEQ_NO
AND SRC.SYS_CR_DT < CHK.SYS_CR_DT
AND SRC.SYS_CR_DT < TO_DATE('2012-12-12', 'yyyy-mm-dd')
WHERE CHK.SYS_CR_DT IS NULL
ORDER BY SRC.STU_NO ASC, SRC.STU_SEQ_NO ASC, SRC.CURR_SSN_IND DESC , SRC.PSEUDO_SSN_IND DESC
【问题讨论】:
-
是否可以将 stu_ssn_tbl 转换为临时表并根据您提供的规则使用干净的数据填充新表 stu_ssn_tbl_final?
-
我的第一个想法是使用 CTE 简化输入数据,但 3 亿行最好创建一个新表
-
是的,我没有任何存储限制......但是......这是 do_not_use 列背后的想法,通过将列设置为“Y”并选择在哪里删除这些记录do_not_use != 'Y'
-
现在无法提供有效的查询 - 但我可以在星期一尝试(可以访问 Oracle 数据库)。此类查询背后的想法是进行常规连接(包含所有重复数据)并添加有关哪些规则已完成以及哪些未完成的信息列,并且只选择最佳结果。
-
到目前为止,我的想法是通过最佳匹配选择,并将这些记录的 do_not_use 列更新为 'N',将表连接到自身 do_not_use != 'N' 并进行下一个最佳匹配,等等,直到规则得到满足。然后在我从 account_tbl 实际加入时添加到加入子句 do_not_use = 'N'