「週平均ユーザー」数(仕様の私の理解によると、「毎日、その日と過去6日間に見られた個別のuser_idの数」)を取得するには、以下の行に沿ってクエリを実行します。使用することができます。(クエリは「1日平均ユーザー」数も返します。
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT FLOOR(k.ts/86400) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT FLOOR(l.ts/86400) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > d.day - 7
GROUP BY d.day
ORDER BY d.day
(私はまだこれのテストを実行していませんが、後で実行し、修正が必要な場合はこのステートメントを更新します。)
このクエリは、特定の日のユーザーのリスト(行ソースからu
)をログテーブルの一連の日(d
行ソースから)に結合します。結合述語(ON句)に表示される文字通りの「7」に注意してください。これにより、ユーザーリストが過去6日間に「一致」します。
これを拡張して、たとえばSELECTリストに別の式を追加することにより、過去3日間の個別のユーザー数を取得することもできます。
, COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day
そのリテラル「7」は、より広い範囲を取得するために増やすことができます。そして、上記の式のリテラル3は、任意の日数を取得するように変更できます...前日の行(からd
)が。からの各行に十分に結合されていることを確認する必要がありu
ます。
パフォーマンスに関する注意:インラインビュー(またはMySQLでは派生テーブルと呼ばれる)が原因で、これらのインラインビューの結果セットを中間のMyISAMテーブルに具体化する必要があるため、このクエリはそれほど高速ではない場合があります。
u
最適ではない可能性があるため、エイリアスされたインラインビュー。ログテーブルに直接参加する方が速い場合があります。特定の日のユーザーの一意のリストを取得するという観点から考えていました。これは、インラインビューでのクエリによって得られたものです。何が起こっているのかを概念化するのは私にとって簡単でした。そして、同じユーザーが何百人も1日入力した場合、他の日に参加する前に、インラインビューで多数の重複が削除されると考えていました。返される日数を制限するWHERE句はu
、d
インラインビュー内に追加するのが最適です。(d
インラインビューには、6日前に追加する必要があります。)
DATE(ts)
別の注意点として、ts列がTIMESTAMPデータ型の場合、式を使用して日付部分を抽出する傾向があります。ただし、整数ではなく、結果セットにDATEデータ型が返されます。これは、指定した結果セットとは異なります。)
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT DATE(k.ts) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT DATE(l.ts) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > DATE_ADD(d.day, INTERVAL -7 DAY)
GROUP BY d.day
ORDER BY d.day