sql - 复合类型数组上的 SUM 和 GROUP BY

标签 sql postgresql types aggregate-functions composite-types

我有一列,其数据类型为复合类型(text, decimal, timestamp) 的数组。我想创建一个查询来对复合类型的双列的总和求和。我还想在日期时间的日期(日-月-年)上执行分组。

谁能给我一个例子来解释这是如何完成的?

表的定义及类型:

create type stage as (
   Stage_Name        text,
   Stage_Distance    decimal,
   Stage_Start_Time  timestamp
);

CREATE TABLE "Event" (
  "Id" serial NOT NULL,
  "Location" text,
  "Date_Range" daterange,
  "Surface" text,
  "Stage_Information" stage[],
  CONSTRAINT "PK_Event" PRIMARY KEY ("Id")
);

示例数据

{"(Newtownards,1.5,\"2015-04-03 18:28:00\")"
,"(\"Bulls Brook\",13.4,\"2015-04-04 09:04:00\")"}

预期结果:

总和(1.5 + 13.4) = 14.9

按 2015-04-03、2015-04-04 分组

最佳答案

由于缺少信息,假设当前的 Postgres 版本为 9.4。

合理的设计

首先,考虑database normalization .一个额外的表而不是列 "Stage_Information" 通常是更好的解决方案:

CREATE TABLE stage (
  stage_id  serial PRIMARY KEY
, event_id  int NOT NULL REFERENCES event
, name      text        -- possibly NOT NULL
, distance  numeric     -- possibly NOT NULL
, starttime timestamp   -- possibly NOT NULL
);

它也不会占用更多的磁盘空间,数组开销与表开销相似。只有附加索引需要更多空间。但是基表上的许多查询会更快,更新会便宜,一切都会更干净、更简单。

不要将带引号和不带引号的大写字母与您的标识符混合使用。这是非常容易出错的。如果可以,只使用不带引号的合法小写名称。

查询将是:

SELECT e.id, s.starttime::date AS day
     , sum(s.distance) AS sum_distance
FROM   "Event" e
LEFT   JOIN stage s ON s.event_id = e.id
WHERE  e.id = 1
GROUP  BY 1, 2;

手头问题的解决方案

虽然坚持当前的设计,但您需要 unnest()将聚合函数应用于其元素的数组。然后你需要分解复合值。使用 LATERAL 连接:

SELECT e.id, <b>(</b>s.st<b>)</b>.stage_start_time::date AS day
     , sum(<b>(</b>s.st<b>)</b>.stage_distance) AS sum_distance
FROM   "Event" e
LEFT   JOIN LATERAL unnest(e."Stage_Information") s(st) ON true
WHERE  e.id = 1
GROUP  BY 1, 2;

请注意 (s.st)(未嵌套列的列别名)两边的括号。您需要那些来访问 composite type (row type) 的元素.

为什么 LEFT JOIN LATERAL ... ON true

关于sql - 复合类型数组上的 SUM 和 GROUP BY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29310815/

相关文章:

sql - 如何让 GROUP BY 选择 "earliest"结果?

sql - DISTINCT 有两个 array_agg(或一个 array_agg 里面有元组)?

sql - 获取 n 个分组类别并将其他类别加总为一个

c++ - 函数模板参数的类型推导

c++ - 如何指定 GetDelegateForFunctionPointer 的调用类型 System : Func?

sql - "x IS NULL"和 "NOT (x IS NOT NULL)"有什么区别?

sql - 使用组和区间数据查找岛屿

sql - 在 Oracle 中将 mm/dd/yyyy 转换为 yyyy-mm-dd

java - PostgresQL 和 Hibernate 自动生成(不是 PK)值

java - java如何比较两个不同大小的原始数据类型