Django 1対多(one2many)でリレーションされた子テーブルの集計値を取得する

外部キーによって子テーブルが親テーブルのIDを参照している場合に、親テーブルのオブジェクトから、その子テーブルの任意カラムの合計値を取得するサンプルです。

以下のようなモデルを想定します。

 

なお、子テーブルのデータを単純に表示したいだけであれば、テンプレート変数「子テーブルのモデル名_set」だけで事足ります。

例えば、views.pyで、

としていれば、テンプレートでは、

のようにすることで可能です。

このとき、子テーブルの一部のカラムの値を合計(この場合は”defective_weight”)して取得したい場合は、”子テーブルのモデル名__カラム名”で子テーブルにアクセスできます。

テンプレートは以下のようになります。

 

ただし、複数の子テーブルをリレーションした場合は、計算が合わなくなります。例えば以下のようなモデルです。

先ほどと同じやり方でクエリセットを構成すると、

となりますが、これだと計算が合わなくなります。なぜなら、テーブル結合の方法がLEFT OUTER JOINとなるからです。

不良カテゴリ1と不良カテゴリ2の対象レコード数が異なっていた場合、結合後のテーブルの行数が、レコード数の多い方のテーブルに合わせた行数となります。

したがって、不良カテゴリ1の行数が4, 不良カテゴリ2の行数が2だった場合、不良カテゴリ2をSumしたときに、4行分を合計してしまいます。

これを避けるにはINNER JOINするべきなのですが、ORMではなるべく生のSQLは触りたくありません。

これを手っ取り早く解決するにはサブクエリを使い、子テーブルを個別に参照して計算し、結合します。ただし多少重くなります。

 

いずれにせよ、このようにしておけば、filterで歩留りの大小順に集計したりもできますので、便利です。

 

参考サイト)

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*