2013-03-15 7 views
0

전자 메일 상태에 대한 보고서를 작성하려고하고 있으며 매월 기록을 유지해야합니다. 여기 여러 날짜 열로 그룹화

데이터에 대한 내 테이블 구조입니다 :

sent_on date; 
sent boolean; 
open date; 
clicked date; 

내가 될 것으로 예상 최종 출력 :

Month | Year | Sent Count | Open Count | Clicked Count 

나는 개인 성명 등을 할 경우 내가 할 수 있다는 것을 알고

Select MONTH(sent_on), YEAR(sent_on), count(sent_on) FROM my_table 
WHERE sent = true; 

Select MONTH(open), YEAR(open), count(open) FROM my_table; 

Select MONTH(clicked), YEAR(clicked), count(clicked) FROM my_table; 

여러분이 도와 주며 간단한 아이디어를 제공 할 수 있습니까? 나는 뭔가를 놓치고 있다고 확신한다.

SELECT m, y, sent_count, open_count, clicked_count 
FROM 
    (SELECT MONTH(sent_on) as m, YEAR(sent_on) as y 
    FROM my_table 
    WHERE sent = true 
    GROUP BY MONTH(sent_on), YEAR(sent_on) 
    UNION ALL 
    SELECT MONTH(open), YEAR(open) 
    FROM my_table 
    WHERE sent = true 
    GROUP BY MONTH(open), YEAR(open) 
    UNION ALL 
    SELECT MONTH(open), YEAR(open) 
    FROM my_table 
    WHERE sent = true 
    GROUP BY MONTH(open), YEAR(open)) d 
LEFT JOIN 
(Select MONTH(sent_on) as m , YEAR(sent_on) as y, count(sent_on) sent_count 
FROM my_table 
WHERE sent = true 
GROUP BY MONTH(sent_on), YEAR(sent_on)) s on (s.y=d.y and s.m=d.m) 
LEFT JOIN 
(Select MONTH(open) as m , YEAR(open) as y, count(open) open_count 
FROM my_table 
WHERE sent = true 
GROUP BY MONTH(open), YEAR(open)) o on (o.y=d.y and o.m=d.m) 
LEFT JOIN 
(Select MONTH(clicked) as m , YEAR(clicked) as y, count(clicked) clicked_count 
FROM my_table 
WHERE sent = true 
GROUP BY MONTH(clicked), YEAR(clicked)) c on (c.y=d.y and c.m=d.m); 

개방 세웠 및 전송을 클릭 : PS 사용하여 SQL은 여기

+0

어떤 DBMS의 성능을 얻기 위해 쿼리 folowing 양식을 시작할 수 있습니다 당신이 사용하고 있습니까? –

+0

아니요, 날짜입니다. 우리는 이메일을 열었거나 클릭 한 날짜를 알기 위해 날짜를 선택해야했습니다. – Milan

+0

@ Lieven 우리는 POSTGRESQL을 사용하고 있습니다. – Milan

답변

1

SQL Fiddle

select 
    date_trunc('month', d) "month", 
    count(sent and sent_on = d or null) sent_on, 
    count(open = d or null) open, 
    count(clicked = d or null) clicked 
from 
    t 
    inner join 
    generate_series(
     (select least(min(sent_on), min(open), min(clicked)) from t), 
     (select greatest(max(sent_on), max(open), max(clicked))from t) 
     , '1 day' 
    ) s(d) on s.d in (t.sent_on, t.open, t.clicked) 
group by 1 
order by 1 
+0

@user 하루가 아닌 월 단위로 그룹화되도록 편집되었습니다. –

+0

@user'sent' 부울을 설명하기위한 새로운 편집. –

+0

'count' 문이 잘못되었습니다. 'sd = '2011 년 1 월 1 일'sent_on = '2013 년 1 월 1 일'open = '2/2/2013'에 'sd = (t.sent_on, t.open, t.clicked) '및'count (open)'은 '*/1/2013'기간 동안이 레코드를 계산합니다 (''2/2/2013''). –

0

가 확대됨에 코드를 necessarly하지 않습니다.

UPDATE은 : 조건부 다음 그룹 결과, 날짜 피벗 해제

Select MONTH(sent_on) sm, YEAR(sent_on) sy, 
     MONTH(OPEN) om, YEAR(OPEN) oy, 
     MONTH(clicked) cm, YEAR(clicked) cy, 
     count(sent_on) sent_cnt, count(clicked) clicked_cnt, count(open) open_cnt 
FROM my_table 
WHERE sent = true 
GROUP BY MONTH(sent_on), YEAR(sent_on), 
     MONTH(OPEN), YEAR(OPEN), 
     MONTH(clicked), YEAR(clicked); 
+0

나는 이것을 한 번의 스캔으로 테이블을 통과하려고 실제로 시도하고있었습니다. 내가 부모의 의견에 언급했듯이, 나는 세 가지 다른 선택을했을 것입니다. – Milan

+0

싱글 스캔을 시도하겠습니다. –

0

:

SELECT 
    MONTH(eventdate) AS Month, 
    YEAR (eventdate) AS Year, 
    COUNT(CASE eventkind WHEN 'sent_on' THEN 1 END) AS SentCount, 
    COUNT(CASE eventkind WHEN 'open' THEN 1 END) AS OpenCount, 
    COUNT(CASE eventkind WHEN 'clicked' THEN 1 END) AS ClickedCount 
FROM (
    SELECT 
    x.eventkind, 
    CASE x.eventkind 
     WHEN 'sent_on' THEN sent_on 
     WHEN 'open' THEN open 
     WHEN 'clicked' THEN clicked 
    END AS eventdate 
    FROM my_table AS t 
    CROSS JOIN (VALUES ('sent_on', 'open', 'clicked')) AS x (eventkind) 
    WHERE t.sent = true 
) AS s 
GROUP BY 
    MONTH(eventdate), 
    YEAR (eventdate) 
; 
관련 문제