Postgresql에서 누적 합계 계산
나는 매일 등록 된 구독자 수를 사용 count
하고 group by
있습니다.
SELECT created_at, COUNT(email)
FROM subscriptions
GROUP BY created at;
결과:
created_at count
-----------------
04-04-2011 100
05-04-2011 50
06-04-2011 50
07-04-2011 300
대신 매일 누적 구독자 수를 얻고 싶습니다. 어떻게 얻을 수 있습니까?
created_at count
-----------------
04-04-2011 100
05-04-2011 150
06-04-2011 200
07-04-2011 500
더 큰 데이터 세트의 경우 창 함수 는 이러한 종류의 쿼리를 수행하는 가장 효율적인 방법입니다. 셀프 조인처럼 테이블은 각 날짜에 한 번이 아니라 한 번만 스캔됩니다. 또한 훨씬 더 간단 해 보입니다. :) PostgreSQL 8.4 이상은 창 기능을 지원합니다.
이것은 다음과 같습니다.
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
여기 OVER
에 창이 생성됩니다. 순서대로 ORDER BY created_at
개수를 합산해야 함을 의미합니다 created_at
.
편집 : 하루 안에 중복 이메일을 제거하려면을 사용할 수 있습니다 sum(count(distinct email))
. 불행히도 이것은 다른 날짜를 교차하는 중복을 제거하지 않습니다.
모든 중복 을 제거 하려면 가장 쉬운 방법은 하위 쿼리 및 DISTINCT ON
. 이것은 이메일을 가장 이른 날짜로 분류합니다 (내가 created_at를 오름차순으로 정렬하고 있기 때문에 가장 빠른 날짜를 선택하기 때문입니다) :
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM (
SELECT DISTINCT ON (email) created_at, email
FROM subscriptions ORDER BY email, created_at
) AS subq
GROUP BY created_at;
에 색인을 생성하는 (email, created_at)
경우이 쿼리도 너무 느려서는 안됩니다.
(테스트를 원하는 경우 샘플 데이터 세트를 만든 방법입니다.)
create table subscriptions as
select date '2000-04-04' + (i/10000)::int as created_at,
'foofoobar@foobar.com' || (i%700000)::text as email
from generate_series(1,1000000) i;
create index on subscriptions (email, created_at);
사용하다:
SELECT a.created_at,
(SELECT COUNT(b.email)
FROM SUBSCRIPTIONS b
WHERE b.created_at <= a.created_at) AS count
FROM SUBSCRIPTIONS a
SELECT
s1.created_at,
COUNT(s2.email) AS cumul_count
FROM subscriptions s1
INNER JOIN subscriptions s2 ON s1.created_at >= s2.created_at
GROUP BY s1.created_at
I assume you want only one row per day and you want to still show days without any subscriptions (suppose nobody subscribes for a certain date, do you want to show that date with the balance of the previous day?). If this is the case, you can use the 'with' feature:
with recursive serialdates(adate) as (
select cast('2011-04-04' as date)
union all
select adate + 1 from serialdates where adate < cast('2011-04-07' as date)
)
select D.adate,
(
select count(distinct email)
from subscriptions
where created_at between date_trunc('month', D.adate) and D.adate
)
from serialdates D
The best way is to have a calendar table: calendar ( date date, month int, quarter int, half int, week int, year int )
Then, you can join this table to make summary for the field you need.
ReferenceURL : https://stackoverflow.com/questions/5698452/count-cumulative-total-in-postgresql
'IT이야기' 카테고리의 다른 글
C- 구조체의 메모리 정렬 (0) | 2021.04.12 |
---|---|
수행하기 위해 만들어진 F # 언어 (0) | 2021.04.12 |
getdate ()의 날짜 부분을 얻는 방법 (0) | 2021.04.12 |
ember.js + 핸들 바 : 렌더 vs 아울렛 vs 부분 vs 뷰 vs 컨트롤 (0) | 2021.04.12 |
rmarkdown : pandoc : pdflatex를 찾을 수 없습니다. (0) | 2021.04.11 |