16

メールアドレスとそれらのメールアドレスがテーブルに追加された日付のデータセットがあります。さまざまな日付の電子メールアドレスの複数のエントリが存在する可能性があります。たとえば、以下のデータセットがある場合。その日付から3日前までの間にある個別の電子メールの日付と数を取得したいと考えています。

Date   | email  
-------+----------------
1/1/12 | test@test.com
1/1/12 | test1@test.com
1/1/12 | test2@test.com
1/2/12 | test1@test.com
1/2/12 | test2@test.com
1/3/12 | test@test.com
1/4/12 | test@test.com
1/5/12 | test@test.com
1/5/12 | test@test.com
1/6/12 | test@test.com
1/6/12 | test@test.com
1/6/12 | test1@test.com

3の期間を使用すると、結果セットは次のようになります。

date   | count(distinct email)
-------+------
1/1/12 | 3
1/2/12 | 3
1/3/12 | 3
1/4/12 | 3
1/5/12 | 1
1/6/12 | 2

以下のクエリを使用して日付範囲の明確なカウントを取得できますが、日ごとの範囲のカウントを取得しようとしているため、数百の日付の範囲を手動で更新する必要はありません。

select test.date, count(distinct test.email)  
from test_table as test  
where test.date between '2012-01-01' and '2012-05-08'  
group by test.date;
4

5 に答える 5

16

テストケース:

CREATE TABLE tbl (date date, email text);
INSERT INTO tbl VALUES
  ('2012-01-01', 'test@test.com')
, ('2012-01-01', 'test1@test.com')
, ('2012-01-01', 'test2@test.com')
, ('2012-01-02', 'test1@test.com')
, ('2012-01-02', 'test2@test.com')
, ('2012-01-03', 'test@test.com')
, ('2012-01-04', 'test@test.com')
, ('2012-01-05', 'test@test.com')
, ('2012-01-05', 'test@test.com')
, ('2012-01-06', 'test@test.com')
, ('2012-01-06', 'test@test.com')
, ('2012-01-06', 'test1@test.com`')
;

クエリ - にエントリが存在する日のみを返しますtbl:

SELECT date
     ,(SELECT count(DISTINCT email)
       FROM   tbl
       WHERE  date BETWEEN t.date - 2 AND t.date -- period of 3 days
      ) AS dist_emails
FROM   tbl t
WHERE  date BETWEEN '2012-01-01' AND '2012-01-06'  
GROUP  BY 1
ORDER  BY 1;

または -その日の行がない場合でも、指定された範囲内のすべての日を返します。

SELECT date
     ,(SELECT count(DISTINCT email)
       FROM   tbl
       WHERE  date BETWEEN g.date - 2 AND g.date
      ) AS dist_emails
FROM  (SELECT generate_series(timestamp '2012-01-01'
                            , timestamp '2012-01-06'
                            , interval  '1 day')::date) AS g(date);

デシベル<>ここでフィドル

結果:

day        | dist_emails
-----------+------------
2012-01-01 | 3
2012-01-02 | 3
2012-01-03 | 3
2012-01-04 | 3
2012-01-05 | 1
2012-01-06 | 2

これは最初はウィンドウ関数の仕事のように思えましたが、適切なウィンドウ フレームを定義する方法が見つかりませんでした。また、ドキュメントごとに:

集約ウィンドウ関数は、通常の集約関数とは異なり、関数の引数リスト内で使用することをDISTINCT許可していません。ORDER BY

そのため、代わりに相関サブクエリで解決しました。それが一番賢い方法だと思います。

ところで、「上記の日付から 3 日前まで」は4日間の期間になります。あなたの定義はそこで矛盾しています。

少し短くなりますが、数日間遅くなります。

SELECT g.date, count(DISTINCT email) AS dist_emails
FROM  (SELECT generate_series(timestamp '2012-01-01'
                            , timestamp '2012-01-06'
                            , interval  '1 day')::date) AS g(date)
LEFT   JOIN tbl t ON t.date BETWEEN g.date - 2 AND g.date
GROUP  BY 1
ORDER  BY 1;

関連している:

于 2012-05-11T03:33:54.310 に答える
0

日付を指定する代わりに、常に dateadd 関数を使用できます。

test.date > dateadd(dd,-7,getdate())
于 2012-10-17T11:52:54.510 に答える
0

SQLサーバーで:

`select test.date, count(distinct test.email) from test_table as test  where convert(date,test.date) between '2012-01-01' and '2012-05-08' group by test.date`

お役に立てれば。

于 2012-05-11T01:40:26.887 に答える