【问题标题】:Rule based select with source tracking具有源跟踪的基于规则的选择
【发布时间】:2021-12-06 16:42:45
【问题描述】:

以下是我在编写高效 SQL 时遇到问题的示例数据集示例:

  1. 有一个目标表 T1 有 5 列 ID(主键)、NAME、CATEGORY、HEIGHT、LINEAGE

  2. T1 从 3 个来源获取数据 - source1, source2, source3

  3. 映射表定义了必须以什么顺序从哪个源中选择哪一列的规则

  4. 如果某个源的列具有 NULL 值,则检查下一个源以获取该值 - 这就是规则

  5. 所以基于规则的目标表列的值如下ID = 1:

     Name: A12, CATEGORY: T1, HEIGHT: 4, Lineage: S3-S1-S1
    

    基于规则的目标表列的值如下ID = 2:

     NAME: B, CATEGORY: T22, HEIGHT: 5, Lineage: S3-S2-S1
    
  6. 合并到目标的逻辑应该是这样的:

     Merge into Target T
     using (select statement with rank based rules from 3 source tables) on 
    
     when matched then
    
     when not matched then
    

问题:关于以一种有效的方式编写此 Merge 是否还应更新合并中的 Lineage 的任何建议?

【问题讨论】:

  • 您能解释一下地图的工作原理吗?身份证有什么提示吗?您描述的示例 Lineage 是否正确?
  • ID 是目标中的主键,这是给定的。逻辑是使用 MAP 表中的优先级为 ID 构建最佳记录,并将该最佳记录推送到目标中。 Lineage 在应用优先规则后告诉 ID 哪个列值来自哪个源。
  • 假设 s1、s2、s3 是另一个元数据表中 SOURCE1、SOURCE2、SOURCE 3 的简称。
  • 但是您是根据什么原因选择第一个示例的 S3-S1-S1 和第二个示例的 S3-S2-S1?什么是映射键?
  • MAP 表显示,NAME 的最佳提供者是 SOURCE3,如果为 NULL,则为 SOURCE1,否则为 SOURCE2。因此,对于 ID 1,SOURCE3 具有“A12”,因此 ID 1 的 NAME 的血统是 S3。实际上两者都是 S3-S2-S1。以上是笔误,见谅。

标签: sql snowflake-cloud-data-platform


【解决方案1】:
  • 首先,MAP 表必须有一个列可以为映射提供优先级
  • 那么你应该 PIVOT 这个表。
  • 下一步是合并所有源表的 UNION ALL。
  • 最后,我们可以使用 FIRST_VALUE 函数连接所有并选择我们的值。
  • 有了这样的结果,您可以在 MERGE 中替换它。

用于测试的结构和样本数据:

CREATE OR REPLACE TABLE SOURCE1 (
    ID int,
    NAME string,
    CATEGORY string,
    HEIGHT numeric);

CREATE OR REPLACE TABLE SOURCE2 (
    ID int,
    NAME string,
    CATEGORY string,
    HEIGHT numeric);
    
CREATE OR REPLACE TABLE SOURCE3 (
    ID int,
    NAME string,
    CATEGORY string,
    HEIGHT numeric);    
    
CREATE OR REPLACE TABLE MAP (
    PRIORITY int,
    SOURCE_COLUMN string,
    SOURCE_TABLE string);
    
INSERT INTO SOURCE1 (ID, NAME, CATEGORY, HEIGHT)
VALUES (1, 'A', 'T1', 4), 
       (2, 'B', 'T2', 5),
       (3, 'C', 'T3', 6);    
       
INSERT INTO SOURCE2 (ID, NAME, CATEGORY, HEIGHT)
VALUES (1, 'A1',  'T1',  4.4), 
       (2, 'B1',  'T22', 6),
       (3,  NULL, 'T3',  7.2);     
       
INSERT INTO SOURCE3 (ID, NAME, CATEGORY, HEIGHT)
VALUES (1, 'A12', 'T21', NULL), 
       (2, 'B',    NULL, 6),
       (3, 'C3', 'T3',   NULL);     
       
INSERT INTO MAP (PRIORITY, SOURCE_COLUMN, SOURCE_TABLE)
VALUES (1, 'NAME',     'SOURCE3'), 
       (2, 'NAME',     'SOURCE1'),
       (3, 'NAME',     'SOURCE2'), 
       (1, 'CATEGORY', 'SOURCE2'),
       (2, 'CATEGORY', 'SOURCE3'), 
       (3, 'CATEGORY', 'SOURCE1'),
       (1, 'HEIGHT',   'SOURCE1'), 
       (2, 'HEIGHT',   'SOURCE2'),
       (3, 'HEIGHT',   'SOURCE3');  

以及我对解决方案的建议:

WITH _MAP AS (
  SELECT *
  FROM MAP
  PIVOT (MAX(SOURCE_TABLE) FOR SOURCE_COLUMN IN ('NAME', 'CATEGORY', 'HEIGHT')) AS p(PRIORITY, NAME, CATEGORY, HEIGHT)
), _SRC AS (       
  SELECT 'SOURCE1' AS SOURCE_TABLE, ID, NAME, CATEGORY, HEIGHT FROM SOURCE1
  UNION ALL
  SELECT 'SOURCE2' AS SOURCE_TABLE, ID, NAME, CATEGORY, HEIGHT FROM SOURCE2
  UNION ALL
  SELECT 'SOURCE3' AS SOURCE_TABLE, ID, NAME, CATEGORY, HEIGHT FROM SOURCE3
)
SELECT DISTINCT _SRC.ID, 
       FIRST_VALUE(_SRC.NAME) OVER(PARTITION BY _SRC.ID ORDER BY MN.PRIORITY) AS NAME,
       FIRST_VALUE(_SRC.CATEGORY) OVER(PARTITION BY _SRC.ID ORDER BY MC.PRIORITY) AS CATEGORY,
       FIRST_VALUE(_SRC.HEIGHT) OVER(PARTITION BY _SRC.ID ORDER BY MH.PRIORITY) AS HEIGHT, 
       REPLACE(FIRST_VALUE(_SRC.SOURCE_TABLE) OVER(PARTITION BY _SRC.ID ORDER BY MN.PRIORITY) || '-' ||
               FIRST_VALUE(_SRC.SOURCE_TABLE) OVER(PARTITION BY _SRC.ID ORDER BY MC.PRIORITY) || '-' ||
               FIRST_VALUE(_SRC.SOURCE_TABLE) OVER(PARTITION BY _SRC.ID ORDER BY MH.PRIORITY), 'SOURCE', 'S') AS LINEAGE
  FROM _SRC
  LEFT JOIN _MAP AS MN ON _SRC.SOURCE_TABLE = MN.NAME AND _SRC.NAME IS NOT NULL
  LEFT JOIN _MAP AS MC ON _SRC.SOURCE_TABLE = MC.CATEGORY AND _SRC.CATEGORY IS NOT NULL
  LEFT JOIN _MAP AS MH ON _SRC.SOURCE_TABLE = MH.HEIGHT AND _SRC.HEIGHT IS NOT NULL;

结果:

+----+------+----------+--------+----------+
| ID | NAME | CATEGORY | HEIGHT | LINEAGE  |
+----+------+----------+--------+----------+
|  1 | A12  | T1       |      4 | S3-S2-S1 |
|  2 | B    | T22      |      5 | S3-S2-S1 |
|  3 | C3   | T3       |      6 | S3-S2-S1 |
+----+------+----------+--------+----------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-20
    • 2017-02-07
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2022-01-14
    • 2021-05-08
    • 1970-01-01
    相关资源
    最近更新 更多