如何在全范围内平均减少 SQL 查询的结果行?

Posted

技术标签:

【中文标题】如何在全范围内平均减少 SQL 查询的结果行?【英文标题】:How to reduce result rows of SQL query equally in full range? 【发布时间】:2016-04-29 21:49:50 【问题描述】:

我有与日期相关的值。例如,我需要选择 10 年的数据。标准查询结果大约有 3000 行,但我需要在 400px 宽度的图表上显示它们,并通过其余的 api 将它们发送到手机。因此,最好将数据减少到 400 个值。

是否有任何内置方法如何在 SQL Server 或 PostgreSQL 中全面减少数据?我该怎么做?

【问题讨论】:

limit 400 或其他与greatest-n-per-group相关的技术? wheregroup by 等...如何过滤数据取决于您自己,而且不可能有一个完全符合您要求的内置函数。 对于 SQL Server,您可以使用 "SELECT TOP 400 * FROM MyTable" ,我想这取决于您的具体要求。 这个问题真的需要两个rdbms的答案吗?因为确切的答案在 PostgreSQL 和 SQL server 中可能不同 不,一个引擎的提示就足够了。我希望原理是一样的。 【参考方案1】:

Postgres 中,width_bucket() 正是您要寻找的东西 - 将基础表中的任意数量的行 (N) 细化为给定的(最好更小) 数据点数 (n)。您可以添加对每个数据点有贡献的行数来表示权重。

一个小障碍:我们需要width_bucket() 的变体在double precisionnumeric 数字上运行,而不是timestamp 等。只需提取 epoch 即可使用。

假设这个表定义和当前的 Postgres 版本:

CREATE TABLE tbl (
  tbl_id serial PRIMARY KEY
, value  numeric NOT NULL
, created_at timestamptz NOT NULL
);

查询:

SELECT width_bucket(extract(epoch FROM t.created_at), x.min_epoch, x.max_epoch, 400) AS pix
     , round(avg(t.value), 2) AS avg  -- round is optional
     , count(*) AS weight
FROM   big t
CROSS  JOIN (SELECT extract(epoch FROM min(created_at)) AS min_epoch
                  , extract(epoch FROM max(created_at)) AS max_epoch FROM big) x
GROUP  BY 1
ORDER  BY 1;

结果:

pix | avg    | weight
----+--------+------
1   | 152.58 | 7
2   | 155.16 | 8
3   | 148.89 | 7
...

返回 400 行 - 除非 N n,在这种情况下您会得到 N 行。

相关:

Multiple averages over evenly spaced intervals Aggregating (x,y) coordinate point clouds in PostgreSQL

【讨论】:

以上是关于如何在全范围内平均减少 SQL 查询的结果行?的主要内容,如果未能解决你的问题,请参考以下文章

具有 unnest 的 PostgreSQL 查询不返回空值的结果行

限制 PostgreSQL 最小时间间隔的结果行

Ms Access SQL:如何防止 Select 查询重复

SQL数据库的多表查询

如何将 SQL 查询结果行作为具有不同标题名称的列? [关闭]

SQL:时间维度和计算平均值