-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathuser_statistics.sql
166 lines (165 loc) · 4.14 KB
/
user_statistics.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
DROP MATERIALIZED VIEW IF EXISTS user_statistics;
CREATE MATERIALIZED VIEW user_statistics AS
WITH general AS (
SELECT
user_id,
array_agg(id) changesets,
max(coalesce(closed_at, created_at)) last_edit,
count(*) changeset_count,
sum(coalesce(total_edits, 0)) edit_count,
max(updated_at) updated_at
FROM changesets
GROUP BY user_id
),
country_counts AS (
SELECT
user_id,
code,
count(*) changesets,
sum(coalesce(total_edits, 0)) edits
FROM changesets
JOIN changesets_countries ON changesets.id = changesets_countries.changeset_id
JOIN countries ON changesets_countries.country_id = countries.id
GROUP BY user_id, code
),
countries AS (
SELECT
user_id,
jsonb_object_agg(code, changesets) country_changesets,
jsonb_object_agg(code, edits) country_edits
FROM country_counts
GROUP BY user_id
),
edit_day_counts AS (
SELECT
user_id,
date_trunc('day', coalesce(closed_at, created_at))::date AS day,
count(*) changesets,
sum(coalesce(total_edits, 0)) edits
FROM changesets
WHERE coalesce(closed_at, created_at) IS NOT NULL
GROUP BY user_id, day
),
edit_days AS (
SELECT
user_id,
jsonb_object_agg(day, changesets) day_changesets,
jsonb_object_agg(day, edits) day_edits
FROM edit_day_counts
GROUP BY user_id
),
editor_counts AS (
SELECT
RANK() OVER (PARTITION BY user_id ORDER BY sum(coalesce(total_edits, 0)) DESC) AS rank,
user_id,
editor,
count(*) changesets,
sum(coalesce(total_edits, 0)) edits
FROM changesets
WHERE editor IS NOT NULL
GROUP BY user_id, editor
),
editors AS (
SELECT
user_id,
jsonb_object_agg(editor, changesets) editor_changesets,
jsonb_object_agg(editor, edits) editor_edits
FROM editor_counts
WHERE rank <= 10
GROUP BY user_id
),
hashtag_counts AS (
SELECT
RANK() OVER (PARTITION BY user_id ORDER BY sum(coalesce(total_edits, 0)) DESC) AS rank,
user_id,
hashtag,
count(*) changesets,
sum(coalesce(total_edits)) edits
FROM changesets
JOIN changesets_hashtags ON changesets.id = changesets_hashtags.changeset_id
JOIN hashtags ON changesets_hashtags.hashtag_id = hashtags.id
GROUP BY user_id, hashtag
),
hashtags AS (
SELECT
user_id,
jsonb_object_agg(hashtag, changesets) hashtag_changesets,
jsonb_object_agg(hashtag, edits) hashtag_edits
FROM hashtag_counts
WHERE rank <= 50
GROUP BY user_id
),
measurements AS (
SELECT
id,
user_id,
key,
value
FROM changesets
CROSS JOIN LATERAL jsonb_each(measurements)
),
aggregated_measurements_kv AS (
SELECT
user_id,
key,
sum((value->>0)::numeric) AS value
FROM measurements
GROUP BY user_id, key
),
aggregated_measurements AS (
SELECT
user_id,
jsonb_object_agg(key, value) measurements
FROM aggregated_measurements_kv
GROUP BY user_id
),
counts AS (
SELECT
id,
user_id,
key,
value
FROM changesets
CROSS JOIN LATERAL jsonb_each(counts)
),
aggregated_counts_kv AS (
SELECT
user_id,
key,
sum((value->>0)::numeric) AS value
FROM counts
GROUP BY user_id, key
),
aggregated_counts AS (
SELECT
user_id,
jsonb_object_agg(key, value) counts
FROM aggregated_counts_kv
GROUP BY user_id
)
SELECT
user_id AS id,
users.name,
measurements,
counts,
last_edit,
changeset_count,
edit_count,
editor_changesets,
editor_edits,
day_changesets,
day_edits,
country_changesets,
country_edits,
hashtag_changesets,
hashtag_edits,
updated_at
FROM general
LEFT OUTER JOIN countries USING (user_id)
LEFT OUTER JOIN editors USING (user_id)
LEFT OUTER JOIN edit_days USING (user_id)
LEFT OUTER JOIN hashtags USING (user_id)
LEFT OUTER JOIN aggregated_measurements USING (user_id)
LEFT OUTER JOIN aggregated_counts USING (user_id)
JOIN users ON user_id = users.id;
CREATE UNIQUE INDEX IF NOT EXISTS user_statistics_id ON user_statistics(id);