Sql 如何将函数作为查询的一部分包含在中?

Sql 如何将函数作为查询的一部分包含在中?,sql,postgresql,plpgsql,crosstab,Sql,Postgresql,Plpgsql,Crosstab,我查询Postgres数据库以获取过去4年的统计数据。 但是,我无法找出正确的语法来替换硬编码日期 在中,作为带有函数的查询的一部分 说:date\u part('year',current\u date)-1而不是“2012” 从交叉表中选择* 选择客户,日期/零件(“年”,日期)作为SalesDate ,总和(总计)::整数作为合成器 从统计 其中日期部分(“年”,日期)>日期部分(“年”,当前日期)-5 和日期部分(“年”,日期)答案 SQL的一个原则是:可以动态提供值,但标识符是静态的

我查询Postgres数据库以获取过去4年的统计数据。
但是,我无法找出正确的语法来替换硬编码日期 在
中,作为带有函数的查询的一部分

说:
date\u part('year',current\u date)-1而不是
“2012”

从交叉表中选择*
选择客户,日期/零件(“年”,日期)作为SalesDate
,总和(总计)::整数作为合成器
从统计
其中日期部分(“年”,日期)>日期部分(“年”,当前日期)-5
和日期部分(“年”,日期)答案
SQL的一个原则是:可以动态提供,但标识符是静态的

外部调用是一个基本SQL语句,列定义列表由标识符组成,而不是值。(这就是为什么您必须双引号引用以数字开头的非法标识符。)因此,您不能在此位置使用函数调用。这是不可能的

可能的解决办法 解决这个问题有很多棘手的办法。。 您可以创建一个plpgsql函数,该函数返回一个值,并提交一个定义良好的复合类型的参数,该类型还包含列名。但这是非常高级的内容。为此,您需要熟悉plpgsql

考虑我在这个相关问题下的综合回答:

答案的后半部分是给你的

由于您需要一个定义良好的复合类型,因此必须在以这种方式调用函数之前创建一个类型,或者只创建一个临时表(自动提供类型)。您可以使用
DO
语句自动执行此操作,该语句使用动态SQL从当前日期派生列名……我从未说过这很简单,但这是可能的

基本查询 同时,您的
crosstab()
查询可以得到改进:

SELECT * FROM crosstab(
    $$
    SELECT client
          ,date_part ('year', date) AS salesdate
          ,sum(total)::int AS synthese
    FROM   statistic
    WHERE  date >= date_trunc('year', now()) - interval '5y'
    AND    date <  date_trunc('year', now())
    GROUP  BY 1,2
    ORDER  BY 1,2
    $$

    ,$$VALUES 
         (date_part('year', now()) - 4)
        ,(date_part('year', now()) - 3)
        ,(date_part('year', now()) - 2)
        ,(date_part('year', now()) - 1)
    $$
    )
AS  (client text
     ,"2009" text
     ,"2010" text
     ,"2011" text
     ,"2012" text);
从交叉表中选择*(
$$
选择客户端
,日期/零件('年',日期)作为销售日期
,总和(合计)::整数作为合成数
从统计
其中日期>=日期(“年”,现在())-间隔“5y”
日期
  • 使用美元报价以避免引用地狱
  • 重写您的
    WHERE
    条件,以便它们可以使用索引。
剩下的是品味和风格的问题。

回答 SQL的一个原则是:可以动态提供,但标识符是静态的

外部调用是一个基本SQL语句,列定义列表由标识符组成,而不是值。(这就是为什么您必须双引号引用以数字开头的非法标识符。)因此,您不能在此位置使用函数调用。这是不可能的

可能的解决办法 解决这个问题有很多棘手的办法。。 您可以创建一个plpgsql函数,该函数返回一个值,并提交一个定义良好的复合类型的参数,该类型还包含列名。但这是非常高级的内容。为此,您需要熟悉plpgsql

考虑我在这个相关问题下的综合回答:

答案的后半部分是给你的

由于您需要一个定义良好的复合类型,因此必须在以这种方式调用函数之前创建一个类型,或者只创建一个临时表(自动提供类型)。您可以使用
DO
语句自动执行此操作,该语句使用动态SQL从当前日期派生列名……我从未说过这很简单,但这是可能的

基本查询 同时,您的
crosstab()
查询可以得到改进:

SELECT * FROM crosstab(
    $$
    SELECT client
          ,date_part ('year', date) AS salesdate
          ,sum(total)::int AS synthese
    FROM   statistic
    WHERE  date >= date_trunc('year', now()) - interval '5y'
    AND    date <  date_trunc('year', now())
    GROUP  BY 1,2
    ORDER  BY 1,2
    $$

    ,$$VALUES 
         (date_part('year', now()) - 4)
        ,(date_part('year', now()) - 3)
        ,(date_part('year', now()) - 2)
        ,(date_part('year', now()) - 1)
    $$
    )
AS  (client text
     ,"2009" text
     ,"2010" text
     ,"2011" text
     ,"2012" text);
从交叉表中选择*(
$$
选择客户端
,日期/零件('年',日期)作为销售日期
,总和(合计)::整数作为合成数
从统计
其中日期>=日期(“年”,现在())-间隔“5y”
日期
  • 使用美元报价以避免引用地狱
  • 重写您的
    WHERE
    条件,以便它们可以使用索引。

剩下的是品味和风格的问题。

是的,你的文章写得更清楚了——这样高质量的答案对学习来说真是太好了:)-因为将结果导出到一个报告I平面,以便对结果进行后处理,以便轻松修改当前日期标题部分。TksYes您的书写更加清晰-这样的高质量答案对学习非常有用:)-因为将结果导出到一个报告I平面,以便对结果进行后处理,以便轻松修改当前日期标题部分.Tks