いくつかありますが。質問。来る。閉じる。私が望むものに(そして私がこのスタックオーバーフローを書いているときに、さらにいくつかを示唆しましたが、どれも私の問題を完全に捉えていません)、SQLの茂みから抜け出す方法を見つけることができないようです。
ユーザー、週、クラスの3つのフィールドを持つ単一のテーブル(user_classification_fctと呼びます)があります(たとえば、第1週のユーザー#1には「通常のユーザー」のクラスがあり、第1週のユーザー#2には'Infrequent User'のクラス)。(余談ですが、クラスをINTとして実装しましたが、SQLを整理する際に、VARCHARの形式で読みやすいものを使用したいと考えていました。)
私がやりたいのは、ユーザーの行動が次のように全体としてどのように変化しているかの要約レポートを作成することです。
- 第1週と第2週の両方で通常のユーザーであった50人のユーザーがいました...
- 第1週には通常のユーザーでしたが、第2週にはまれなユーザーに落ちたユーザーが10人いました。
- 第1週の頻度が低いものから第2週の通常のユーザーに変わったユーザーは5人でした
- ... 等々 ...
これを少し注意が必要なのは、ユーザー#5000が第2週にサービスの使用を開始しただけで、第1週のテーブルにレコードがない可能性があることです。その場合、第1週と2週目の「通常のユーザー」(または適切なもの)。テーブルのサイズは厳密には関係ありませんが、5週間分のデータでは、4,200万行を見ているので、4を挿入したくありません。 5週目かそこらでサービスの使用を開始した人のための「非ユーザー」の偽の行。
私には、これは明らかにMySQLでLEFTまたはRIGHT JOINを使用する場合のように見えます。これは、「欠落している」レコードでNULLが発生するためです。
LEFT JOINでWHERE条件とAND条件の両方を使用しようとしましたが、「正しい」答えが得られません(つまり、WHERE条件の末尾の場合、NULL値がまったく得られないか、カウントが多すぎます。以下で使用されるAND制約の場合、個別のユーザーの数(約1,000万)。これを機能させるための最後の試みは次のとおりです。
SELECT
ucf1.class_nm AS 'Class in 2012/15',
ucf2.class_nm AS 'Class in 2012/16',
ucf3.class_nm AS 'Class in 2012/17',
ucf4.class_nm AS 'Class in 2012/18',
ucf5.class_nm AS 'Class in 2012/19',
count(*) AS 'Count'
FROM
user_classification_fct ucf5
LEFT JOIN user_classification_fct ucf4
ON ucf5.user_id=ucf4.user_id
AND ucf5.week_key=201219 AND ucf4.week_key=201218
LEFT JOIN user_classification_fct ucf3
ON ucf4.user_id=ucf3.user_id
AND ucf4.week_key=201218 AND ucf3.week_key=201217
LEFT JOIN user_classification_fct ucf2
ON ucf3.user_id=ucf2.user_id
AND ucf3.week_key=201217 AND ucf2.week_key=201216
LEFT JOIN user_classification_fct ucf1
ON ucf2.user_id=ucf1.user_id
AND ucf2.week_key=201216 AND ucf1.week_key=201215
GROUP BY 1,2,3,4,5;
stackoverflow.comで他のさまざまな質問を見ると、一度に1つずつクエリを実行し、結果セットをUNIONするか、括弧を使用して相互にチェーンする必要があるかもしれませんが、アプローチは(まだ)私が精通しているものではなく、有用なものを返すために1つのLEFT JOIN(つまり、5週目から1週目まで)を取得することさえできません。
データベース製品の切り替えはオプションではないため、ヒントは大いにありがたいです。MySQLで機能する提案をいただければ幸いです。