在Vertica中与子查询合并

时间:2017-01-05 12:02:46

标签: sql-server vertica

我试图在Vertica中使用Merge命令仅从源表中插入不同的记录到目标表。我曾使用子查询在SQL中尝试过同样的事情,但在vertica中它不允许。 以下是错误:

[Vertica][VJDBC](5665) ERROR: Subquery in MERGE is not supported

请帮助我。

提前致谢

3 个答案:

答案 0 :(得分:1)

在vertica merge中无法使用Subquery。

MERGE INTO Target TGT
USING (Select distinct * from Sources) as SRC 
ON TGT.CD = SRC.CD

我创建了一个视图:

Select distinct * from Sources

像这样使用它:

MERGE INTO Target TGT
    USING SRC_VW as SRC 
    ON TGT.CD = SRC.CD
它解决了目的。只想将其张贴以供将来使用。

答案 1 :(得分:0)

您是否需要使用大数据量执行MERGE操作?

然后,您应该考虑启用优化的MERGE 计划而不是标准的MERGE,这要快得多。

如果您感兴趣,请大声说出来,我会在此向您解释详细信息。

快乐的玩耍

Marco the Sane

答案 2 :(得分:0)

优化MERGE可能性。

我将它基于残缺的慢速变化维度表。它带来了这个想法,但不要把它作为现实中任何事物的设计蓝图......!

假设您在目标表中拥有这些行。 cust_key是代理主键,cust_id和cust_to_dt的组合是表的另一个唯一标识符:

cust_key|cust_id|cust_to_dt|cust_first_name  |cust_last_name    |cust_phoneno      |cust_loyalty_lvl|cust_org_id
       1|      7|9999-12-31|Lionel           |Prosser           |+41(0)79 387 31 07|               1|          0
       2|     14|9999-12-31|Hotblack         |Desiato           |+41(0)79 387 31 14|               2|          0
       3|     21|9999-12-31|Slartibartfast   |Slartibartfast    |+41(0)79 387 31 21|               3|          0
       4|     28|9999-12-31|Pizpot           |Gargravarr        |+41(0)79 387 31 28|               4|          0
       5|     35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35|               5|          0
       6|     42|9999-12-31|Fook             |Fook              |+41(0)79 387 31 42|               6|          0

目标表的定义如下:

-- create a stand-alone sequence 
CREATE SEQUENCE source_seq;
-- the target's surrogate key defaults to its sequence's NEXTVAL ….
CREATE TABLE target (
  cust_key         BIGINT DEFAULT target_seq.NEXTVAL NOT NULL
, cust_id          BIGINT
, cust_to_dt       DATE
, cust_first_name  NCHAR VARYING(30)
, cust_last_name   NCHAR VARYING(30)
, cust_phoneno     NCHAR VARYING(30)
, cust_loyalty_lvl BIGINT
, cust_org_id      BIGINT
, PRIMARY KEY(cust_key)
)
UNSEGMENTED ALL NODES;

您的源表 - 没有启动器的代理键值 - 看起来像这样。 6行是现有的更新行,1行是新行,Thor和cust_id 43。:

cust_id|cust_to_dt|cust_first_name  |cust_last_name    |cust_phoneno      |cust_loyalty_lvl|cust_org_id
      7|9999-12-31|Lionel           |Prosser           |+41(0)79 387 31 07|               2|          0
     14|9999-12-31|Hotblack         |Desiato           |+41(0)79 387 31 14|               3|          0
     21|9999-12-31|Slartibartfast   |Slartibartfast    |+41(0)79 387 31 21|               4|          0
     28|9999-12-31|Pizpot           |Gargravarr        |+41(0)79 387 31 28|               5|          0
     35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35|               6|          0
     42|9999-12-31|Fook             |Fook              |+41(0)79 387 31 42|               7|          0
     43|9999-12-31|Thor             |Thor              |+41(0)79 623 84 75|               6|          1

您的MERGE源表的构建方式与目标表类似。:

CREATE TABLE merge_src LIKE target INCLUDING PROJECTIONS;

您可以从增量表中填充它,以便从目标中选择现有的代理键,并且在它们不存在的地方使用target_seq.NEXTVAL来获取新的代理键。为此,您使用cust_idcust_to_dt的组合将源加入目标,这是另一种唯一标识目标行的可能性:

INSERT /*+ DIRECT */ INTO merge_src
SELECT
  IFNULL(tgt.cust_key,target_seq.NEXTVAL) AS cust_key
, src.cust_id
, src.cust_to_dt
, src.cust_first_name
, src.cust_last_name
, src.cust_phoneno
, src.cust_loyalty_lvl
, src.cust_org_id
FROM source src
LEFT
JOIN target tgt
USING(cust_id,cust_to_dt)
;

您的合并源表现在看起来像这样 - 带有cust_id 43的新行Thor,获取一个新的代理键:

SQL>select * from merge_src;
cust_key|cust_id|cust_to_dt|cust_first_name  |cust_last_name    |cust_phoneno      |cust_loyalty_lvl|cust_org_id
       1|      7|9999-12-31|Lionel           |Prosser           |+41(0)79 387 31 07|               2|          0
       2|     14|9999-12-31|Hotblack         |Desiato           |+41(0)79 387 31 14|               3|          0
       3|     21|9999-12-31|Slartibartfast   |Slartibartfast    |+41(0)79 387 31 21|               4|          0
       4|     28|9999-12-31|Pizpot           |Gargravarr        |+41(0)79 387 31 28|               5|          0
       5|     35|9999-12-31|Know-Nothing-Bozo|the Non-Wonder Dog|+41(0)79 387 31 35|               6|          0
       6|     42|9999-12-31|Fook             |Fook              |+41(0)79 387 31 42|               7|          0
250,007|     43|9999-12-31|Thor             |Thor              |+41(0)79 623 84 75|               6|          1

merge_src和target之间的MERGE使用优化的MERGE,使用ON子句中的代理键(我刚用[...]占位符替换了GraphViz格式的有向图对象的代码)。特别注意DELETE的访问路径 - 它有一个MERGEJOIN(输入预先排序)并使用Side Information Passing(SIP1):

SQL>EXPLAIN
...>MERGE /*+DIRECT*/
...>INTO target t
...>USING merge_src s
...> ON s.cust_key         = t.cust_key
...>WHEN MATCHED THEN UPDATE SET
...>  cust_key         = s.cust_key
...>, cust_id          = s.cust_id
...>, cust_to_dt       = s.cust_to_dt
...>, cust_first_name  = s.cust_first_name
...>, cust_last_name   = s.cust_last_name
...>, cust_phoneno     = s.cust_phoneno
...>, cust_loyalty_lvl = s.cust_loyalty_lvl
...>, cust_org_id      = s.cust_org_id
...>WHEN NOT MATCHED THEN INSERT (
...>  cust_key
...>, cust_id
...>, cust_to_dt
...>, cust_first_name
...>, cust_last_name
...>, cust_phoneno
...>, cust_loyalty_lvl
...>, cust_org_id
...>) VALUES (
...>  s.cust_key
...>, s.cust_id
...>, s.cust_to_dt
...>, s.cust_first_name
...>, s.cust_last_name
...>, s.cust_phoneno
...>, s.cust_loyalty_lvl
...>, s.cust_org_id
...>);
QUERY PLAN
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------

EXPLAIN MERGE /*+DIRECT*/ INTO target t USING merge_src s ON s.cust_key = t.cust_key WHEN MATCHED THEN UPDATE SET cust_key = s.cust_key , cust_id = s.cust_id , cust_to_dt = s.cust_to_dt , cust_first_name = s.cust_first_name , cust_last_name = s.cust_last_name , cust_phoneno = s.cust_phoneno , cust_loyalty_lvl = s.cust_loyalty_lvl , cust_org_id = s.cust_org_id WHEN NOT MATCHED THEN INSERT ( cust_key , cust_id , cust_to_dt , cust_first_name , cust_last_name , cust_phoneno , cust_loyalty_lvl , cust_org_id ) VALUES ( s.cust_key , s.cust_id , s.cust_to_dt , s.cust_first_name , s.cust_last_name , s.cust_phoneno , s.cust_loyalty_lvl , s.cust_org_id )

Access Path:
+-DML INSERT [Cost: 0, Rows: 0]
|  Target Projection: scd.target_super
|  Target Prep:
| +---> STORAGE ACCESS for s [Cost: 40, Rows: 7 (NO STATISTICS)] (PATH ID: 3)
| |      Projection: scd.merge_src_super
| |      Materialize: s.cust_key, s.cust_id, s.cust_to_dt, s.cust_first_name, s.cust_last_name, s.cust_phoneno, s.cust_loyalty_lvl, s.cust_org_id


[...]

Lock Map - Table (Mode)
----------------------------------------------
target(I)
----------------------------------------------
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------

EXPLAIN MERGE /*+DIRECT*/ INTO target t USING merge_src s ON s.cust_key = t.cust_key WHEN MATCHED THEN UPDATE SET cust_key = s.cust_key , cust_id = s.cust_id , cust_to_dt = s.cust_to_dt , cust_first_name = s.cust_first_name , cust_last_name = s.cust_last_name , cust_phoneno = s.cust_phoneno , cust_loyalty_lvl = s.cust_loyalty_lvl , cust_org_id = s.cust_org_id WHEN NOT MATCHED THEN INSERT ( cust_key , cust_id , cust_to_dt , cust_first_name , cust_last_name , cust_phoneno , cust_loyalty_lvl , cust_org_id ) VALUES ( s.cust_key , s.cust_id , s.cust_to_dt , s.cust_first_name , s.cust_last_name , s.cust_phoneno , s.cust_loyalty_lvl , s.cust_org_id )

Access Path:
+-DML DELETE [Cost: 0, Rows: 0]
|  Target Projection: scd.target_super (DELETE ON CONTAINER)
|  Target Prep:
| +---> JOIN MERGEJOIN(inputs presorted) [Semi] [Cost: 11, Rows: 7 (NO STATISTICS)] (PATH ID: 1)
| |      Join Cond: (VAL(2) = t.cust_key)
| | +-- Outer -> STORAGE ACCESS for t [Cost: 5, Rows: 6 (NO STATISTICS)] (PATH ID: 2)
| | |      Projection: scd.target_super
| | |      Materialize: t.cust_key
| | |      Runtime Filter: (SIP1(MergeJoin): t.cust_key)
| | +-- Inner -> SELECT [Cost: 5, Rows: 7 (NO STATISTICS)] (PATH ID: 3)
| | | +---> STORAGE ACCESS for s [Cost: 5, Rows: 7 (NO STATISTICS)] (PATH ID: 4)
| | | |      Projection: scd.merge_src_super
| | | |      Materialize: s.cust_key

Lock Map - Table (Mode)
----------------------------------------------
target(X)
----------------------------------------------

希望这一切都有道理......

快乐的比赛 -

Marco the Sane