「ユーザーごとに購入したアイテムの平均数、最大数、最小数」を取得するためのクエリを作成しようとしています。
データソースは、次の単純な販売記録テーブルです。
class SalesRecord(models.Model):
id = models.IntegerField(primary_key=True)
user_id = models.IntegerField()
product_code = models.CharField()
price = models.IntegerField()
created_at = models.DateTimeField()
ユーザーが購入したすべてのアイテムについて、このテーブルに新しいレコードが挿入されます。[注]:このバックエンドシステムはユーザー情報を管理しないため、同じデータベース内のテーブルへの外部キーではありませuser_id
ん。値は、製品のフロントエンド部分によって提供されます。
クエリを作成する試みは次のとおりです。
q = SalesRecord.objects.all()
q = q.values('user_id').annotate( # group by user and count the # of records
count=Count('id'), # (= # of items)
).order_by()
result = q.aggregate(Max('count'), Min('count'), Avg('count'))
コードを実行しようとするとProgrammingError
、最後の行でaが発生します。
(1064、「SQL構文にエラーがあります。MySQLサーバーのバージョンに対応するマニュアルで、「FROM(SELECT .AS
sales_records
、COUNT(.`」の1行目)の近くで使用する正しい構文を確認してください」)user_id
user_id
sales_records
Djangoのエラー画面は、SQLが
SELECT FROM
(SELECT
`sales_records`.`user_id` AS `user_id`,
COUNT(`sales_records`.`id`) AS `count`
FROM `sales_records`
WHERE (`sales_records`.`created_at` >= %s AND `sales_records`.`created_at` <= %s )
GROUP BY `sales_records`.`user_id` ORDER BY NULL) subquery
何も選択していません!誰かがこれを行う正しい方法を教えてもらえますか?
Djangoのハッキング
で選択したフィールドのキャッシュをクリアdjango.db.models.sql.query.BaseQuery.get_aggregation()
すると、問題が解決するようです。これが修正または回避策であるかどうかはわかりませんが。
@@ -327,10 +327,13 @@
# Remove any aggregates marked for reduction from the subquery
# and move them to the outer AggregateQuery.
+ self._aggregate_select_cache = None
+ self.aggregate_select_mask = None
for alias, aggregate in self.aggregate_select.items():
if aggregate.is_summary:
query.aggregate_select[alias] = aggregate
- del obj.aggregate_select[alias]
+ if alias in obj.aggregate_select:
+ del obj.aggregate_select[alias]
...結果が得られます:
{'count__max': 267, 'count__avg': 26.2563, 'count__min': 1}