bra*_*rad 7 sql postgresql correlated-subquery
我有两张桌子points
,contacts
而且我试图points.score
按月分组每个联系人的平均值. 请注意,积分和联系人不相关,我只想要在一个月内创建的积分总和除以该月份存在的联系人数量.
所以,我需要总结按created_at月份分组的点数,我需要只计算那个月份的联系人数量.这是最后一部分让我烦恼的部分.我不确定如何在子查询中使用外部查询中的列.我试过这样的事情:
SELECT SUM(score) AS points_sum,
EXTRACT(month FROM created_at) AS month,
date_trunc('MONTH', created_at) + INTERVAL '1 month' AS next_month,
(SELECT COUNT(id) FROM contacts WHERE contacts.created_at <= next_month) as contact_count
FROM points
GROUP BY month, next_month
ORDER BY month
Run Code Online (Sandbox Code Playgroud)
所以,我正在提取我的积分总和的实际月份,同时,得到next_month的开头,这样我就可以说"让我知道他们创建的联系人的数量是<next_month"
但它抱怨说column next_month doesn't exist
这是可以理解的,因为子查询对外部查询一无所知.资格赛points.next_month
也不起作用.
那么有人能指出我如何实现这一目标的正确方向吗?
点
score | created_at
10 | "2011-11-15 21:44:00.363423"
11 | "2011-10-15 21:44:00.69667"
12 | "2011-09-15 21:44:00.773289"
13 | "2011-08-15 21:44:00.848838"
14 | "2011-07-15 21:44:00.924152"
Run Code Online (Sandbox Code Playgroud)
往来
id | created_at
6 | "2011-07-15 21:43:17.534777"
5 | "2011-08-15 21:43:17.520828"
4 | "2011-09-15 21:43:17.506452"
3 | "2011-10-15 21:43:17.491848"
1 | "2011-11-15 21:42:54.759225"
Run Code Online (Sandbox Code Playgroud)
sum,month和next_month(没有subselect)
sum | month | next_month
14 | 7 | "2011-08-01 00:00:00"
13 | 8 | "2011-09-01 00:00:00"
12 | 9 | "2011-10-01 00:00:00"
11 | 10 | "2011-11-01 00:00:00"
10 | 11 | "2011-12-01 00:00:00"
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 10
现在有了联系人的总和.我的第一稿每月使用新的联系人,这显然不是OP想要的.
WITH c AS (
SELECT created_at
,count(id) OVER (order BY created_at) AS ct
FROM contacts
), p AS (
SELECT date_trunc('month', created_at) AS month
,sum(score) AS points_sum
FROM points
GROUP BY 1
)
SELECT p.month
,EXTRACT(month FROM p.month) AS month_nr
,p.points_sum
,( SELECT c.ct
FROM c
WHERE c.created_at < (p.month + interval '1 month')
ORDER BY c.created_at DESC
LIMIT 1) AS contacts
FROM p
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
points
.如果您希望所有月份(包括缺少的points
月份)生成带有generate_series()和LEFT JOIN 的月份列表.您的原始查询形式可以这样工作:
SELECT month
,EXTRACT(month FROM month) AS month_nr
,points_sum
,(SELECT count(*)
FROM contacts c
WHERE c.created_at < (p.month + interval '1 month')) AS contact_count
FROM (
SELECT date_trunc('MONTH', created_at) AS month
,sum(score) AS points_sum
FROM points p
GROUP BY 1
) p
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
解决错误的直接原因是将聚合放入子查询中.你以一种不可能的方式混合水平.
我希望我的变体在大桌子上稍快一些.关于较小的表不确定.如果你用测试结果报告回来会很棒.
加上一个小修复:<
而不是<=
.