これは複雑な問題のようです。難しい問題に思えるかどうかに関係なく、小さな問題から取り組み始めることは決して悪い考えではありません。
たとえば、要件に応じて、先週登録されたすべてのユーザー (ユーザーのみ) を返すクエリから開始できます。つまり、今から 6 日後の日から開始できます。
SELECT *
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
次のステップでは、結果を日付別にグループ化し、すべてのグループの行を数えることができます。
SELECT
created_at,
COUNT(*) AS user_count
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
GROUP BY created_at
created_at
がdatetime
またはの場合、グループ化基準としてtimestamp
使用します。DATE(created_at)
SELECT
DATE(created_at) AS created_at,
COUNT(*) AS user_count
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
GROUP BY DATE(created_at)
ただし、出力に絶対日付は必要ないようですが、などの相対日付のみが必要です。その場合、2 つの日付間の日数を返す関数を使用して、(数値) オフセットを生成できます。今日から、それらの値でグループ化します。today
today - 1 day
DATEDIFF()
SELECT
DATEDIFF(CURDATE(), created_at) AS created_at,
COUNT(*) AS user_count
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
GROUP BY DATE(created_at)
列created_at
には などの「日付」が含まれ0
、1
まで続き6
ます。today
それらをなどに変換するのtoday-1
は簡単で、最終的なクエリでそれがわかります。ただし、これまでのところ、ユーザーを実際にカウントする必要はなく、ユーザーのリターンをカウントする必要があるため、1 歩後退する必要があるポイントに到達しました (または、おそらく、右に半ステップです)。 . users
そのため、現時点で必要な実際の作業データセットは次のようになります。
SELECT
id,
DATEDIFF(CURDATE(), created_at) AS day_offset
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
この行セット (派生元の行セット) を結合するためのユーザー ID が必要であり、グループ化基準としてsessions
必要です。day_offset
sessions
次に、同様の変換をテーブルで実行する必要があります。詳細については説明しません。結果のクエリは、次の 2 つの例外を除いて、最後のクエリと非常に同じになると言えば十分です。
DISTINCT の理由は、1 ユーザーおよび 1 日あたり 1 行しか返さないためです。ユーザーが特定の日にセッションをいくつ持っていても、それらを1 つの returnとしてカウントしたいというのが私の理解です。したがって、ここから派生するものは次のsessions
とおりです。
SELECT DISTINCT
user_id,
DATEDIFF(CURDATE(), created_at) AS day_offset
FROM sessions
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
あとは、2 つの派生テーブルを結合し、グループ化を適用し、条件付き集計を使用して必要な結果を取得するだけです。
SELECT
CONCAT('today', IFNULL(CONCAT('-', NULLIF(u.DayOffset, 0)), '')) AS created_at,
SUM(s.DayOffset = 0) AS d0,
SUM(s.DayOffset = 1) AS d1,
SUM(s.DayOffset = 2) AS d2,
SUM(s.DayOffset = 3) AS d3,
SUM(s.DayOffset = 4) AS d4,
SUM(s.DayOffset = 5) AS d5,
SUM(s.DayOffset = 6) AS d6
FROM (
SELECT
id,
DATEDIFF(CURDATE(), created_at) AS DayOffset
FROM users
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
) u
LEFT JOIN (
SELECT DISTINCT
user_id,
DATEDIFF(CURDATE(), created_at) AS DayOffset
FROM sessions
WHERE created_at >= CURDATE() - INTERVAL 6 DAY
) s
ON u.id = s.user_id
GROUP BY u.DayOffset
;
私はこれをテスト/デバッグしていないことを認めなければなりませんが、これが必要な場合は、提供されたデータ サンプルを喜んで使用します。:)