「週平均ユーザー」数(私の仕様の理解によると、「毎日、その日と過去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
から) rowsource)、ログテーブルからの一連の日(d
rowsource)。結合述語(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日前に追加する必要があります。)
別の注意点として、ts列がTIMESTAMPデータ型の場合、DATE(ts)
を使用する傾向があります。 日付部分を抽出する式。ただし、整数ではなく、結果セットに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