如何通过在MERGE中重用计算结果集来节省计算

时间:2016-11-02 20:09:34

标签: sql vertica

我想在SQL join语句中重用以前计算的结果集,我需要每天运行。例如,我有两个表:table_A和table_B,它们共享一个公共密钥,比如ckey。我想在我的查询中使用LEFT JOIN来查找table_A中基于ckey映射到table_B中的数据记录:

SELECT a*, b*
FROM table_A as A
LEFT JOIN table_B as B
ON A.ckey = B.ckey

但是我想在上面的连接中将不匹配的行存储在一个单独的表中,比如说table_C,这样我就可以定期查看它们并稍后更新table_B内容。对于table_A和table_B之间匹配的那些,我想将它们存储在一个新表中(让我们称之为table_C)。为此,我希望使用WITH子句临时存储结果集,如下所示:

CREATE TABLE IF NOT EXISTS table_C (ckey_to_review VARCHAR(10));

WITH left_join_result AS(
SELECT a*, b.ckey as b_ckey
FROM table_A as A
LEFT JOIN table_B as B
ON A.ckey = B.ckey),

non_matchable_data AS(
SELECT distinct ckey
FROM left_join_result AS C
WHERE b_ckey IS NULL),

matchable_data AS(
SELECT *
FROM left_join_result AS C
WHERE b_ckey IS NOT NULL)

/* use MERGE to upsert newly found unmatchable items */
MERGE INTO table_C AS t
USING non_matchable_data AS s
ON t.ckey_to_review = s.ckey
WHEN MATCHED THEN UPDATE SET ckey_to_review = s.ckey
WHEN NOT MATCHED THEN 
    INSERT (ckey_to_review)
    VALUES (s.ckey)

/* then use data from 'matchable_data' above for something other procedures */

我后来才知道WITH clause are only allowed to be used with SELECT statement。为了提供更具体的上下文,我使用Vertica来执行此操作,以防有一些针对此问题的特定于Vertica的解决方案。我只掌握SQL的基本知识,所以我确信有某种设计模式可以指导我做我正在努力做的事情(也就是说,不要求我更多地调用LEFT JOIN而不是一次并重复使用LEFT JOIN的结果集)。

2 个答案:

答案 0 :(得分:2)

老实说,我认为你是在思考它。

因此,要准确回答您的问题,您只需创建本地临时表而不是使用withCREATE LOCAL TEMP TABLE它将在您的会话中提供。顺便说一下,除非specifically enable an optionwith是内嵌视图,否则不会实现。

那就是说,我真想以下就好了。如果您真的希望它有效,那么您将更关注如何对数据进行分段和排序以创建本地合并连接。

SELECT ckey
FROM table_B
MINUS
SELECT ckey
FROM table_A

SELECT ckey
FROM table_B
INTERSECT
SELECT ckey
FROM table_A

答案 1 :(得分:1)

所以你所看到的在DataWarehouse(或DataMart)世界中很常见......你正在寻找一种INCREMENTAL加载策略,其中有几种方法。

insert into [matched] (PK)
select key from table1 join table2 on key
where key not in (select PK from [Matched])

第一次它会成为一个doozie,基于你对500米记录的评论...增量应该不那么。

您还可以考虑其他各种策略:

  • nolocks(取决于如何填充源表)以减少锁争用

  • 分块以减少事务大小(日志文件增长等)

  • maxdop管理吞吐量与执行时间对资源负载