就像已经提供的@Andomar一样:大多数RDBMS要求按未聚合的每一列进行分组-
查询中的其他任何位置(包括
SELECt列表,还包括
WHERe子句等)。
因此
op.id覆盖了整个表格,这应该适用于您当前的查询:
GROUP BY op.id, c.name, 5, t.name, p.name
5作为一个 位置参考 的
SELECT列表,这也允许在Postgres的。这只是重复长表达的简写形式:
CASE WHEN op.receiving_account_id IS NOT NULL THEN CASE WHEN op.account_id IS NULL THEN ac2.name ELSE ac.name || ' -> ' || ac2.name END ELSE ac.nameEND
我从您的名字得出,您与之间有一个:m关系,
operation并通过
tag实现
operation_tag。所有其他联接似乎都没有将行相乘,因此单独聚合标签会更有效-
就像@Andomar暗示的那样,只需弄清楚逻辑即可。
这应该工作:
SELECT op.id , op.name , c.name , CASE -- amountsign WHEN op.receiving_account_id IS NOT NULL THEN CASE WHEN op.account_id IS NULL THEN '+' ELSE '=' END ELSE '-' END || ' ' || op.amount || ' z艂' AS amount , CASE -- account WHEN op.receiving_account_id IS NOT NULL THEN CASE WHEN op.account_id IS NULL THEN ac2.name ELSE ac.name || ' -> ' || ac2.name END ELSE ac.name END AS account , t.name AS type , **to_char(op.date, 'DD.MM.YY') || ' ' || op.time AS date** -- see below , p.name AS place , ot.tagsFROM operation opLEFT JOIN category c ON op.category_id = c.idLEFT JOIN type t ON op.type_id = t.idLEFT JOIN account ac ON op.account_id = ac.idLEFT JOIN account ac2 ON op.receiving_account_id = ac2.idLEFT JOIN place p ON op.place_id = p.id**LEFT JOIN ( SELECt operation_id, string_agg(t.name, ', ') AS tags FROM operation_tag ot LEFT JOIN tag t ON t.id = ot.tag_id GROUP BY 1 ) ot ON op.id = ot.operation_id****ORDER BY op.date DESC, op.time DESC** ;
阿西德斯
您可以替换:
CASE --date WHEN op.time IS NOT NULL THEN to_char(op.date, 'DD.MM.YY') || ' ' || op.time ELSE to_char(op.date, 'DD.MM.YY')END AS date
具有以下较短的等效项:
concat_ws(' ', to_char(op.date, 'DD.MM.YY'), op.time) AS date但是,由于这两个列均已定义
NOT NULL,因此您可以进一步简化为:
to_char(op.date, 'DD.MM.YY') || ' ' || op.time AS date
小心一点,您
ORDER BY至少有一个输入列也称为
date。如果使用非限定名称,它将引用 输出 列-这就是您想要的名称(如注释中所阐明)。
但是 ,按文本表示进行排序将无法正确地根据您的时间轴进行排序。按原始值排序,而不是上面我的查询中所建议的。



