栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在SQL查询中使用(func())。*语法避免使用多个函数评估?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在SQL查询中使用(func())。*语法避免使用多个函数评估?

您可以将其包装在子查询中,但是如果没有

OFFSET 0hack
,就不能保证安全。在9.3中,使用
LATERAL
。该问题是由于解析器有效地将宏扩展
*
为列列表而引起的。

解决方法
在哪里:

SELECt (my_func(x)).* FROM some_table;

将计算函数中结果列的

my_func n
时间
n
,公式如下:

SELECt (mf).* FROM (    SELECt my_func(x) AS mf FROM some_table) sub;

通常不会,并且往往不会在运行时添加其他扫描。为了保证不会执行多次评估,您可以使用

OFFSET 0
黑客或滥用
PostgreSQL
的失败来跨
CTE
边界进行优化:

SELECt (mf).* FROM (    SELECt my_func(x) AS mf FROM some_table OFFSET 0) sub;

或者:

WITH tmp(mf) AS (    SELECt my_func(x) FROM some_table)SELECt (mf).* FROM tmp;

在PostgreSQL 9.3中,您可以

LATERAL
用来获得更合理的行为:

SELECt mf.*FROM some_tableLEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;

LEFT JOIN LATERAL ... ON true
即使函数调用不返回任何行,也保留与原始查询类似的所有行。

演示版
创建一个不可内联的函数作为演示:

CREATE OR REPLACe FUNCTION my_func(integer)RETURNS TABLE(a integer, b integer, c integer) AS $$BEGIN    RAISE NOTICE 'my_func(%)',$1;    RETURN QUERY SELECT $1, $1, $1;END;$$ LANGUAGE plpgsql;

和伪数据表:

CREATE TABLE some_table AS SELECT x FROM generate_series(1,10) x;

然后尝试以上版本。您会看到第一个每次调用会引发三个通知;后者只举一个。

为什么?
好问题。这太糟糕了。

看起来像:

(func(x)).*

扩展为:

(my_func(x)).i, (func(x)).j, (func(x)).k, (func(x)).l

在解析,根据一看

debug_print_parse,debug_print_rewritten和debug_print_plan
。(修剪后的)分析树如下所示:

   :targetList (      {TARGETENTRY       :expr          {FIELDSELECT          :arg  {FUNCEXPR  :funcid 57168       ... }         :fieldnum 1          :resulttype 23          :resulttypmod -1          :resultcollid 0         }      :resno 1       :resname i        ...      }      {TARGETENTRY       :expr          {FIELDSELECT          :arg  {FUNCEXPR  :funcid 57168       ... }         :fieldnum 2          :resulttype 20          :resulttypmod -1          :resultcollid 0         }      :resno 2       :resname j        ...      }      {TARGETENTRY       :expr          {FIELDSELECT          :arg  {FUNCEXPR  :funcid 57168   ... }         :fieldnum 3          :...         }      :resno 3       :resname k        ...      }      {TARGETENTRY       :expr          {FIELDSELECT          :arg  {FUNCEXPR  :funcid 57168   ... }         :fieldnum 4...         }      :resno 4       :resname l        ...      }   )

因此,基本上,我们使用的是哑巴分析器黑客工具,通过克隆节点来扩展通配符。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/379224.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号