0

基本上,下面的代码是否有效(如果我不能在 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
);

我也不想使用用户定义的函数,尽管这出现在其他问题中。

4

2 回答 2

0

关于检查计划,MonetDB 支持:

  • PLAN 查看逻辑计划
  • EXPLAIN根据MA​​L指令查看物理计划
  • TRACE与 相同EXPLAIN,但实际执行 MAL 计划并返回所有指令的统计信息。

关于您关于重复子查询的问题,原则上不会重复任何内容,您不需要明确处理它。这是因为默认优化管道包含commonTerms 优化器。您的 SQL 将被翻译成一系列 MAL 指令,并带有重复调用。MAL 的设计很简单:许多短指令调用,有点像汇编,对列进行操作,而不是行(因此,当您考虑执行效率时,不要应用与 SQL Server 相同的推理)。这使得在其上运行一些优化变得更容易。commonTerms 优化器将检测重复调用并尽可能重用所有结果。这是按列完成的。所以你应该真的能够运行你的查询并感到高兴。

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

于 2014-10-11T16:16:05.290 回答
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;
于 2014-06-12T21:12:36.543 回答