在日常开发中,我们常常需要对复杂的 SQL 进行数据血缘分析。
本文重点讨论在具有 * 列的嵌套子查询中建立表和列之间正确关系的挑战。使用 Teradata SQL 代码示例来说明该过程。
本文聚焦于一个别名为 SUBSCRIBER_ 的子查询及其派生的列,这些列在外层查询中被使用。有些列在子查询的选择列表中被明确列出,而其他一些列则来自一个列(SUBSCR.),这个*列引用了 PRD2_ODW.SUBSCRIBER_ 表。
接着,分析检查了外层查询的选择列表,特别是来自 SUBSCRIBER_ 子查询的列。它展示了如何确定每一列的来源:
1、子查询中未显式列出的列(例如,SUBS_ID、ACTIVATION_DATE)源自 * 列,属于 PRD2_ODW.SUBSCRIBER_ 表。
2、子查询中显式列出的列(例如,FIRST_TP_ID、CUST_ID)可追溯到其原始表(在这些情况下为SUBS_CUST)。
此过程有助于将列准确映射到其源表,这对于理解复杂查询和维护具有星形列的嵌套子查询中的数据沿袭至关重要。
以下是演示中使用的 Teradata SQL 代码:
第130行: SUBSCRIBER_是子查询的别名,该子查询的派生列在外查询中使用。
SUBSCRIBER_ 的派生列从第 90 行开始到第 111 行,来自不同的表。还有一个以 SUBSCR 为前缀的星形列 *,它是 PRD2_ODW.SUBSCRIBER_ 表的别名。
现在,让我们看一下外部查询,特别是从第 23 行到第 87 行开始的选择列表部分,我们只关注子查询 SUBSCRIBER_ 中的列。
第23行:SUBSCRIBER_.SUBS_ID,第90行到第111行的选择列表中没有显式列出列SUBSCRIBER_ID,因此该列必须来自SUBSCR.*,而SUBSCR是第112行中PRD2_ODW.SUBSCRIBER_表的别名。
- 结论:SUBS_ID 是表PRD2_ODW.SUBSCRIBER_ 的列
第 25 行: SUBSCRIBER_.REGISTRATION_DATE (NAMED REGISTRATION_DTTM),列 REGISTRATION_DATE 没有显式列在第 90 行到第 111 行的选择列表中,因此该列必须来自 SUBSCR.*,而 SUBSCR 是 PRD2_ODW.SUBSCRIBER_ 表的别名。
- 结论:REGISTRATION_DATE 是表PRD2_ODW.SUBSCRIBER_的列
第26行: SUBSCRIBER_.FIRST_CALL(NAMED FIRST_CALL_DTTM),第90行到第111行的选择列表中没有明确列出列FIRST_CALL,因此该列必须来自SUBSCR.*,而SUBSCR是PRD2_ODW.SUBSCRIBER_表的别名。
- 结论:FIRST_CALL是表PRD2_ODW.SUBSCRIBER_的列。
第 27 行: SUBSCRIBER_.FIRST_TP_ID,列 FIRST_TP_ID 在第 91 行的选择列表中显式列出:SUBS_CUST.FIRST_TP_ID。
- 结论:FIRST_TP_ID是表SUBS_CUST的列
第 28 行: SUBSCRIBER_.CUST_ID,列 CUST_ID 在第 92 行的选择列表中显式列出:SUBS_CUST.CUST_ID。
- 结论:CUST_ID 是表SUBS_CUST 的列
第 30 行: SUBSCRIBER_.DEALER_ID,列 DEALER_ID 在第 102 行的选择列表中显式列出:SUBS_CUST.DEALER_ID。
- 结论:DEALER_ID 是表 SUBS_CUST 的列
第 35 行: SUBSCRIBER_.SRVP_COV_CUST_ID,列 SRVP_COV_CUST_ID 在第 93 行的选择列表中显式列出:SUBS_CUST.SRVP_COV_CUST_ID。
- 结论:SRVP_COV_CUST_ID 是表 SUBS_CUST 的列
第 37 行:SUBSCRIBER_.TP_ID,列 TP_ID 在第 94 行的选择列表中显式列出:SUBS_CUST.TP_ID。
- 结论:TP_ID是表SUBS_CUST的列
第 38 行: SUBSCRIBER_.BLOCK_QUOTA (NAMEDIS_BLOCK_QUOTA),列 BLOCK_QUOTA 在第 95 行的选择列表中显式列出:SUBS_CUST.BLOCK_QUOTA。
- 结论:BLOCK_QUOTA是表SUBS_CUST的列
第 40 行: WHEN (SUBSCRIBER_.REL_CAT_ID < 0) THEN (NULL),列 REL_CAT_ID 在第 96 行的选择列表中显式列出:SUBS_CUST.REL_CAT_ID。
- 结论:REL_CAT_ID 是表 SUBS_CUST 的列
第 47 行: SUBSCRIBER_.STATUS_CHNG_RSN_ID,列 STATUS_CHNG_RSN_ID 在第 97 行的选择列表中显式列出:SUBS_CUST.STATUS_CHNG_RSN_ID。
- 结论:STATUS_CHNG_RSN_ID 是表 SUBS_CUST 的列
第 48 行: SUBSCRIBER_.STATUS_ID,列 STATUS_ID 在第 98 行的选择列表中显式列出:SUBS_CUST.STATUS_ID。
- 结论:STATUS_ID 是表 SUBS_CUST 的列
第 49 行: SUBSCRIBER_.SUBS_TYPE_ID,列 SUBS_TYPE_ID 在第 99 行的选择列表中显式列出:SUBS_CUST.SUBS_TYPE_ID。
- 结论:SUBS_TYPE_ID 是表 SUBS_CUST 的列
第 50 行: SUBSCRIBER_.BRANCH_ID (NAMED BRANCH_ID),列 BRANCH_ID 在第 100 行的选择列表中显式列出:SUBS_CUST.BRANCH_ID。
- 结论:BRANCH_ID 是表 SUBS_CUST 的列
第 61 行: SUBSCRIBER_.BRANCH_ID (NAMED BRANCH_ID),列 BRANCH_ID 在第 100 行的选择列表中显式列出:SUBS_CUST.BRANCH_ID。
- 结论:BRANCH_ID 是表 SUBS_CUST 的列
第 62 行: CAST((SUBSCRIBER_.CALC_PLATFORM_ID) AS DECIMAL(2, 0))(NAMED CALC_PLATFORM_ID),列 CALC_PLATFORM_ID 在第 110 行的选择列表中显式列出:END)(NAMED CALC_PLATFORM_ID),这是一个列别名,基础列是 SUBS_CUST.CALC_PLATFORM_ID。
- 结论:CALC_PLATFORM_ID 是表 SUBS_CUST 的列
第 66 行: WHEN (((SUBSCRIBER_.BRANCH_ID = 61) AND (SUBSCRIBER_.CALC_PLATFORM_ID IN (6,7,8,9))) AND (:_spVV0 >= DATE '2018-04-30')) THEN (0) ,列 BRANCH_ID 在第 100 行的选择列表中显式列出:SUBS_CUST.BRANCH_ID。
- 结论:BRANCH_ID 是表 SUBS_CUST 的列。
第 71 行: CAST((SUBSCRIBER_.LAST_FLASH_DTTM) AS DATE)(NAMED LAST_FLASH_DTTM),列 LAST_FLASH_DTTM 在第 104 行的选择列表中显式列出:SUBS_CLR_FLASH.LAST_FLASH_DTTM。
- 结论:LAST_FLASH_DTTM是表SUBS_CLR_FLASH的列。
第 73 行: WHEN (NOT (SUBSCRIBER_.FLASH_CODE_ID IS NULL)) THEN (SUBSCRIBER_.FLASH_CODE_ID),列 FLASH_CODE_ID 在第 105 行的选择列表中显式列出:SUBS_CLR_FLASH.FLASH_CODE_ID。
- 结论:FLASH_CODE_ID是表SUBS_CLR_FLASH的列
第 77 行: WHEN (NOT (SUBSCRIBER_.IF_NEW_CHURN IS NULL)) THEN (SUBSCRIBER_.IF_NEW_CHURN),列 IF_NEW_CHURN 在第 106 行的选择列表中显式列出:SUBS_CLR_FLASH.IF_NEW_CHURN。
- 结论: IF_NEW_CHURN 是表 SUBS_CLR_FLASH 的列
结论
表 PRD2_ODW.SUBSCRIBER_ 具有以下列:
PRD2_ODW.SUBSCRIBER_.SUBS_ID
PRD2_ODW.SUBSCRIBER_.ACTIVATION_DATE
PRD2_ODW.SUBSCRIBER_.REGISTRATION_DATE
PRD2_ODW.SUBSCRIBER_.FIRST_CALL
参考
数据血缘分析工具:SQLFlow