【问题标题】:How to use DISTINCT with string_agg() and to_timestamp()?如何将 DISTINCT 与 string_agg() 和 to_timestamp() 一起使用?
【发布时间】:2019-09-04 09:34:33
【问题描述】:

我想要逗号分隔的唯一 from_date 在一行中。

所以我在TO_TIMESTAMP() 中使用distinct() 函数,但出现错误。

SELECT string_agg(TO_CHAR(TO_TIMESTAMP(distinct(from_date) / 1000), 'DD-MM-YYYY'), ',')
FROM trn_day_bookkeeping_income_expense 
GROUP BY from_date,enterprise_id having enterprise_id = 5134650;

我想要这样的输出:

01-10-2017,01-11-2017,01-12-2017

但我收到如下错误:

ERROR:  DISTINCT specified, but to_timestamp is not an aggregate function
LINE 1: SELECT string_agg(TO_CHAR(TO_TIMESTAMP(distinct(from_date) /...**

【问题讨论】:

  • from_date是什么数据类型,为什么要在上面使用to_timestamp()?为什么不将时间戳值存储在 timestamp 列中?
  • 数据类型为 bigint。 to_timestamp() 用于将 bigint 转换为日期格式
  • 为什么不将时间戳值存储在timestamp 列中?那么你就不需要每次想要一个正确的时间戳时都调用to_timestamp()
  • 请建议我如何将时间戳值存储在时间戳中
  • 使用数据类型timestamp

标签: sql postgresql timestamp aggregate distinct


【解决方案1】:

DISTINCT 既不是函数也不是运算符,而是 SQL 构造或语法元素。可以添加为主要关键字to the whole SELECT listwithin most aggregate functions

将其添加到子选择中的SELECT 列表(在您的情况下由单个列组成),您还可以在其中廉价地添加ORDER BY。应该产生最佳性能:

SELECT string_agg(to_char(the_date, 'DD-MM-YYYY'), ',') AS the_dates
FROM  (
   SELECT DISTINCT to_timestamp(from_date / 1000)::date AS the_date
   FROM   trn_day_bookkeeping_income_expense 
   WHERE  enterprise_id = 5134650
   ORDER  BY the_date   -- assuming this is the order you want 
   ) sub;

首先生成日期(多个不同的值可能导致相同的日期!)。
然后是DISTINCT 步骤(或GROUP BY)。
(在此期间,可选择添加ORDER BY。)
最后聚合。

(enterprise_id) 或更好的(enterprise_id, from_date) 上的索引应该会大大提高性能。

理想情况下,时间戳以timestamp 类型开始存储。或timestamptz。见:

DISTINCT ON 是标准 SQL DISTINCT 功能的 Postgres 特定扩展。见:

或者,您也可以将DISTINCT ORDER BY)直接添加到聚合函数string_agg()

SELECT string_agg(DISTINCT to_char(to_timestamp(from_date / 1000), 'DD-MM-YYYY'), ',' ORDER BY to_char(to_timestamp(from_date / 1000), 'DD-MM-YYYY')) AS the_dates
FROM   trn_day_bookkeeping_income_expense 
WHERE  enterprise_id = 5134650

但这会很丑陋,难以阅读和维护,而且成本更高。 (使用EXPLAIN ANALYZE 测试)。

【讨论】:

  • @Rahul:我添加了更多解释。
【解决方案2】:

distinct 不是函数,它是应用于选择列表中所有列的运算符,或者是聚合函数的参数。

你可能想要这个:

SELECT string_agg(distinct TO_CHAR(TO_TIMESTAMP(from_date / 1000), 'DD-MM-YYYY'), ',') 
from trn_day_bookkeeping_income_expense 
group by from_date,enterprise_id 
having enterprise_id = 5134650

【讨论】:

    猜你喜欢
    • 2017-02-16
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多