売り注文を格納するMySQL DBテーブルでは、LastReviewed
カラムに売り注文が変更された最後の日付と時刻を保持します(timestamp
、デフォルト値CURRENT_TIMESTAMP
)。私は、特定のユーザーのために、過去90日間、毎日変更された売上の数をプロットしたいと思います。SQL:サブクエリを使用しないクエリでの再利用関数の結果
LastReviewed
からの日数と、その範囲内のレコード数を返すSELECT
を作成しようとしています。私はDATEDIFF()
だけでなく、各レコードのCURDATE()
複数回計算しています
SELECT DATEDIFF(CURDATE(), LastReviewed) AS days, COUNT(*) AS number FROM sales
WHERE UserID=123 AND DATEDIFF(CURDATE(),LastReviewed)<=90
GROUP BY days
ORDER BY days ASC
注意:以下は正常に動作します私のクエリは、あります。これは実際には効果がないようですので、前回の計算の結果をどのように再利用できるかを知りたいと思います。私が試した最初のものでした:
SELECT DATEDIFF(CURDATE(), LastReviewed) AS days, COUNT(*) AS number FROM sales
WHERE UserID=123 AND days<=90
GROUP BY days
ORDER BY days ASC
エラー:Unknown column 'days' in 'where clause'
。だから私はネットの周りを見始めた。別の議論(Can I reuse a calculated field in a SELECT query?)に基づいて、私は次の次のことを試してみました:
SELECT DATEDIFF(CURDATE(), LastReviewed) AS days, COUNT(*) AS number FROM sales
WHERE UserID=123 AND (SELECT days)<=90
GROUP BY days
ORDER BY days ASC
エラー:Unknown column 'days' in 'field list'
。私も次のことを試してみましたよ:
SELECT @days := DATEDIFF(CURDATE(), LastReviewed) AS days,
COUNT(*) AS number FROM sales
WHERE UserID=123 AND @days <=90
GROUP BY days
ORDER BY days ASC
クエリがゼロ結果を返しますので、@days<=90
が、私はSELECT
句に入れてWHERE
句を削除した場合、私は@days
でいくつかの結果を見ることができるにもかかわらずfalse
を返すように見えます90.
以下の値は、私は、サブクエリを使用して動作するように物事を得ている:
SELECT * FROM (
SELECT DATEDIFF(CURDATE(),LastReviewed) AS sales ,
COUNT(*) AS number FROM sales
WHERE UserID=123
GROUP BY days
) AS t
WHERE days<=90
ORDER BY days ASC
は、しかし、私はそれが最も効率的な方法だかどうかを知るodn't。たとえその値がクエリの最初から最後まで同じであっても、このソリューションでもレコードごとに1回、
CURDATE()
を計算することは言うまでもありません。それは無駄ではないですか?私はこれを熟考していますか?ヘルプは大歓迎です。
注:これはCodeReviewにある必要がありますか?私が使用しようとしているコードが実際に動作しないため、ここに投稿しました
FWIWでは、クエリ+サブクエリは安価ではなく、クエリで 'WHERE days <90'を実行するか、' DATEDIFF(CURDATE()、LastReviewed)を繰り返すと結果がより速くなるかどうかを確認できます。 – aneroid
私のポストでは言及していませんでしたが(1分後に追加します)、バグのもう一つのことは、最初から最後まで変更しなくても、すべてのステップで 'CURDATE() 'を計算することですクエリの終わり。 – BeetleJuice