CASE WHEN中的SQL子查询是为查询运行一次,还是每行?

时间:2014-06-12 17:36:44

标签: sql subquery case case-when monetdb

基本上,代码是否有效(如果我不能在MonetDB中使用@变量),或者这会多次调用子查询?

CREATE VIEW sys.share26cuts_2007 (peorglopnr,share26cuts_2007) AS (
SELECT peorglopnr, CASE WHEN share26_2007 < (SELECT QUANTILE(share26_2007,0.25) FROM sys.share26_2007) THEN 1
                        WHEN share26_2007 < (SELECT QUANTILE(share26_2007,0.5) FROM sys.share26_2007) THEN 2
                        WHEN share26_2007 < (SELECT QUANTILE(share26_2007,0.75) FROM sys.share26_2007) THEN 3
                        ELSE 4 END AS share26cuts_2007
FROM sys.share26_2007
);

我宁愿不使用用户定义的函数,尽管这在other questions中出现。

2 个答案:

答案 0 :(得分:0)

例如GoatCO评论了这个问题,这可能是更好的避免。 MonetDB支持的SET命令可以与SELECT一起使用,如下面的代码所示。剩下的问题是为什么所有分位数都为零,而我的数据肯定不是(在使用NULLIF之前我也有零除错误)。我现在展示了更多的代码。

CREATE VIEW sys.over26_2007 (personlopnr,peorglopnr,loneink,below26_loneink) AS (
SELECT personlopnr,peorglopnr,loneink, CASE WHEN fodelsear < 1981 THEN 0 ELSE loneink END AS below26_loneink
FROM sys.ds_chocker_lev_lisaindivid_2007
);
SELECT COUNT(*) FROM over26_2007;

CREATE VIEW sys.share26_2007 (peorglopnr,share26_2007) AS (
SELECT peorglopnr, SUM(below26_loneink)/NULLIF(SUM(loneink),0)
FROM sys.over26_2007
GROUP BY peorglopnr
);
SELECT COUNT(*) FROM share26_2007;

DECLARE firstq double;
SET firstq = (SELECT QUANTILE(share26_2007,0.25) FROM sys.share26_2007);
SELECT firstq;
DECLARE secondq double;
SET secondq = (SELECT QUANTILE(share26_2007,0.5) FROM sys.share26_2007);
SELECT secondq;
DECLARE thirdq double;
SET thirdq = (SELECT QUANTILE(share26_2007,0.275) FROM sys.share26_2007);
SELECT thirdq;
CREATE VIEW sys.share26cuts_2007 (peorglopnr,share26cuts_2007) AS (
SELECT peorglopnr, CASE WHEN share26_2007 < firstq THEN 1
                        WHEN share26_2007 < secondq THEN 2
                        WHEN share26_2007 < thirdq THEN 3
                        ELSE 4 END AS share26cuts_2007
FROM sys.share26_2007
);
SELECT COUNT(*) FROM share26cuts_2007;

答案 1 :(得分:0)

关于检查计划,MonetDB支持:

  • 计划查看逻辑计划
  • EXPLAIN根据MAL说明
  • 查看实际计划
  • TRACEEXPLAIN相同,但实际执行MAL计划并返回所有说明的统计信息。

关于重复子查询的问题,原则上 什么都不会重复,你不需要明确地处理它。 那是因为默认优化管道包含commonTerms optimizer。您的SQL将被转换为一系列MAL指令,具有重复调用。 MAL设计得很简单:许多简短的指令调用,有点像汇编,它们在列上运行,而不是行(因此当你想到时,不会应用与SQL Server相同的推理)执行效率)。这样可以更轻松地对其进行一些优化。 commonTerms优化器将检测重复的调用并重用它可以的所有结果。这是按列完成的。所以你应该真的能够运行你的查询并且开心。

但是,我原则上说 。并非所有案例都会被发现(尽管大部分都会被发现),并且还会有目的地引入一些限制。例如,用于检测重复项的搜索空间是一个窗口(对我来说太小了 - 我已经在我的安装中完全删除了它)在整个MAL计划中:如果重复的指令太远了计划,它将不会是检测。这样做是为了提高效率。在您的情况下,单个查询不是那么大,但如果它是更长视图链的一部分,那么所有这些视图将编译成一个大型MAL计划 - 可能使commonTerms效率降低 - 这实际上取决于实际的查询。