如何将下一组的第一行包含在聚合中?
How to include the first row from the next group in an aggregation?
我在 Postgres 中有一个 table,其中包含类别和值。我想执行聚合,例如每个类别的 avg(value),但包括聚合中下一类别的第一行。
样本table:
id category value
-------------------
1 1 5.4
2 1 2.1
3 2 1.0
4 2 2.6
5 2 0.3
6 3 4.4
7 3 3.8
id
是一个主键,提供了一个顺序。类别按顺序分组并连续。
acceptable(但不是必需的)创建一个像这样的中间 table,它复制相邻的行:
id category value
-------------------
1 1 5.4
2 1 2.1
3 1 1.0 <-- new row
4 2 1.0
5 2 2.6
6 2 0.3
7 2 4.4 <-- new row
8 3 4.4
9 3 3.8
...然后做:
select category, avg(value) group by category from sample_table
如何使用 SQL 语句实现这一点?
我怀疑这可以通过 window 函数和一些复杂的框架子句(如 GROUPS)来完成,但我不知道如何实现。 (见 https://www.postgresql.org/docs/12/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS )
您确认类别数正在稳步增加 1,没有差距。
这是简单案例的简单方法:
SELECT category, avg(value)
FROM (
SELECT category, value
FROM tbl
UNION ALL
( -- parentheses required
SELECT DISTINCT ON (category)
category - 1, value
FROM tbl
WHERE category > (SELECT min(category) FROM tbl) -- eliminate corner case
ORDER BY category, id
)
) sub
GROUP BY 1
ORDER BY 1;
UNION ALL
之后的第二个术语按照您的建议添加行:我取每组的第一行,然后从类别中减去 1。
极端情况:使用 min(category) - 1
添加新类别。可以轻松消除...
任何种类别的通用解决方案(只要定义了顺序):
SELECT category, avg(value)
FROM (
SELECT category, value
FROM tbl
UNION ALL
SELECT lag(category) OVER (ORDER BY category), value
FROM (
SELECT DISTINCT ON (category)
category, value
FROM tbl
ORDER BY category, id
) unicat
) sub
WHERE category IS NOT NULL -- eliminate corner case
GROUP BY 1
ORDER BY 1;
将每个组的第一个值添加到上一个类别
关于DISTINCT ON
:
- Select first row in each GROUP BY group?
我在 Postgres 中有一个 table,其中包含类别和值。我想执行聚合,例如每个类别的 avg(value),但包括聚合中下一类别的第一行。
样本table:
id category value
-------------------
1 1 5.4
2 1 2.1
3 2 1.0
4 2 2.6
5 2 0.3
6 3 4.4
7 3 3.8
id
是一个主键,提供了一个顺序。类别按顺序分组并连续。
acceptable(但不是必需的)创建一个像这样的中间 table,它复制相邻的行:
id category value
-------------------
1 1 5.4
2 1 2.1
3 1 1.0 <-- new row
4 2 1.0
5 2 2.6
6 2 0.3
7 2 4.4 <-- new row
8 3 4.4
9 3 3.8
...然后做:
select category, avg(value) group by category from sample_table
如何使用 SQL 语句实现这一点?
我怀疑这可以通过 window 函数和一些复杂的框架子句(如 GROUPS)来完成,但我不知道如何实现。 (见 https://www.postgresql.org/docs/12/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS )
您确认类别数正在稳步增加 1,没有差距。
这是简单案例的简单方法:
SELECT category, avg(value)
FROM (
SELECT category, value
FROM tbl
UNION ALL
( -- parentheses required
SELECT DISTINCT ON (category)
category - 1, value
FROM tbl
WHERE category > (SELECT min(category) FROM tbl) -- eliminate corner case
ORDER BY category, id
)
) sub
GROUP BY 1
ORDER BY 1;
UNION ALL
之后的第二个术语按照您的建议添加行:我取每组的第一行,然后从类别中减去 1。
极端情况:使用 min(category) - 1
添加新类别。可以轻松消除...
任何种类别的通用解决方案(只要定义了顺序):
SELECT category, avg(value)
FROM (
SELECT category, value
FROM tbl
UNION ALL
SELECT lag(category) OVER (ORDER BY category), value
FROM (
SELECT DISTINCT ON (category)
category, value
FROM tbl
ORDER BY category, id
) unicat
) sub
WHERE category IS NOT NULL -- eliminate corner case
GROUP BY 1
ORDER BY 1;
将每个组的第一个值添加到上一个类别
关于DISTINCT ON
:
- Select first row in each GROUP BY group?