如何将DISTINCT与string_agg()和to_timestamp()结合使用?

时间:2019-09-04 09:34:33

标签: sql postgresql timestamp aggregate distinct

我希望用逗号将唯一的from_date分隔成一行。

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

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) /...**

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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)添加到聚合函数{{1 }}直接:

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 测试)。