我想在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的结果集)。
答案 0 :(得分:2)
因此,要准确回答您的问题,您只需创建本地临时表而不是使用with
。 CREATE LOCAL TEMP TABLE
它将在您的会话中提供。顺便说一下,除非specifically enable an option,with
是内嵌视图,否则不会实现。
那就是说,我真想以下就好了。如果您真的希望它有效,那么您将更关注如何对数据进行分段和排序以创建本地合并连接。
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管理吞吐量与执行时间对资源负载