【问题标题】:Could not choose a best candidate function. You might need to add explicit type casts无法选择最佳候选函数。您可能需要添加显式类型转换
【发布时间】:2017-08-31 22:27:27
【问题描述】:
select
  c_elementvalue.value AS "VALUE",
  c_elementvalue.name AS "NAME",
  rv_fact_acct.postingtype AS "POSTINGTYPE",
  sum(rv_fact_acct.amtacct) AS "AMNT",
  'YTDB' AS "TYPE",
  c_period.enddate AS "ENDDATE",
  max(ad_client.description) AS "COMPANY"
from
  adempiere.c_period,
  adempiere.rv_fact_acct,
  adempiere.c_elementvalue,
  adempiere.ad_client
where
  (rv_fact_acct.ad_client_id =  ad_client.ad_client_id ) and
  (rv_fact_acct.c_period_id = c_period.c_period_id) and
  (rv_fact_acct.account_id = c_elementvalue.c_elementvalue_id) and
  (rv_fact_acct.dateacct BETWEEN  to_date( to_char( '2017-03-01' ,'YYYY') ||'-04-01', 'yyyy-mm-dd')  AND '2017-03-31'  ) AND
  (rv_fact_acct.ad_client_id = 1000000) and
  (rv_fact_acct.c_acctschema_id = 1000000 )and
  (rv_fact_acct.postingtype = 'B')and
  (rv_fact_acct.accounttype in ('R','E') )
group by  c_elementvalue.value , c_elementvalue.name , rv_fact_acct.postingtype , c_period.enddate
order by 5 asc, 1 asc

执行上述 sql 语句(postgres)时收到错误消息。

错误信息:

[Err] ERROR:  function to_char(unknown, unknown) is not unique
LINE 68:  (rv_fact_acct.dateacct BETWEEN  to_date( to_char( '2017-03-...
                                                   ^
HINT:  Could not choose a best candidate function. You might need to add explicit type casts. 

【问题讨论】:

  • 你想用什么逻辑来过滤账户日期?你现在的代码没有意义。

标签: postgresql


【解决方案1】:

您的这部分查询有问题:

to_date( to_char( '2017-03-01' ,'YYYY') ||'-04-01', 'yyyy-mm-dd')

没有任何函数to_char,具有第一个参数字符串。

postgres=# \df to_char 功能列表 ┌────────────┬──────────┬──────────────────┬─────── ────────────────────────────┬────────┐ │ Schema │ Name │ 结果数据类型 │ Argument 数据类型 │ Type │ ╞════════════╪═════════╪══════════════════╪═══════ ════════════════════════════╪════════╡ │ pg_catalog │ to_char │ text │ bigint, text │ normal │ │ pg_catalog │ to_char │ 文本 │ 双精度,文本 │ 普通 │ │ pg_catalog │ to_char │ text │ integer, text │ normal │ │ pg_catalog │ to_char │ 文本 │ 区间、文本 │ 普通 │ │ pg_catalog │ to_char │ text │ numeric, text │ normal │ │ pg_catalog │ to_char │ text │ real, text │ normal │ │ pg_catalog │ to_char │ 文本 │ 没有时区的时间戳,文本 │ 普通 │ │ pg_catalog │ to_char │ 文本 │ 带时区的时间戳,文本 │ 普通 │ └────────────┴──────────┴──────────────────┴──────── ────────────────────────────┴────────┘ (8 行)

您可以将字符串2017-03-01 转换为date 类型。 PostgreSQL 不能自己做,因为有更多的变种:numeric,timestamp, ...

postgres=# select to_date( to_char( '2017-03-01'::date ,'YYYY') ||'-04-01', 'yyyy-mm-dd');
┌────────────┐
│  to_date   │
╞════════════╡
│ 2017-04-01 │
└────────────┘
(1 row)

通常,对日期时间操作使用字符串操作是错误的。 PostgreSQL(和所有 SQL 数据库)有很好的functions 用于日期算术。

例如-任务“获取下个月的第一个日期”可以用表达式来完成:

postgres=# select date_trunc('month', current_date + interval '1month')::date;
┌────────────┐
│ date_trunc │
╞════════════╡
│ 2017-05-01 │
└────────────┘
(1 row)

您可以用SQL语言(宏)编写自定义函数:

postgres=# create or replace function next_month(date) 
           returns date as $$
             select date_trunc('month', $1 + interval '1month')::date $$
           language sql;
CREATE FUNCTION
postgres=# select next_month(current_date);
┌────────────┐
│ next_month │
╞════════════╡
│ 2017-05-01 │
└────────────┘
(1 row)

【讨论】:

    【解决方案2】:

    目前尚不清楚您打算使用什么逻辑来按帐户日期进行过滤,但您当前对to_char()to_date() 的使用似乎是导致错误的原因。如果您只想获取 2017 年 3 月的记录,请使用以下命令:

    rv_fact_acct.dateacct BETWEEN '2017-03-01' AND '2017-03-31'
    

    如果您向我们提供有关您尝试做什么的更多信息,我们可以相应地更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-27
      • 2018-11-08
      • 2017-06-28
      • 2015-04-07
      • 2017-04-25
      • 2020-06-16
      • 2013-09-09
      • 2017-07-16
      相关资源
      最近更新 更多