sql >> データベース >  >> RDS >> PostgreSQL

Rails 3.1 with PostgreSQL:GROUPBYは集計関数で使用する必要があります

    式によって生成されたSQLは有効なクエリではありません。user_idでグループ化しています それに基づいて他の多くのフィールドを選択しますが、他のフィールドをどのように集約するかをDBに指示しません。たとえば、データが次のようになっている場合:

    a  | b
    ---|---
    1  | 1
    1  | 2
    2  | 3
    

    ここで、dbにaでグループ化するように依頼すると また、bを返しますが、値を集計する方法がわかりません1,2 。最小、最大、平均、合計などを選択する必要があるかどうかを判断する必要があります。私が答えを書いていたのと同じように、これをよりよく説明するかもしれない2つの答えがありました。

    ただし、ユースケースでは、dbレベルでのグループ化は必要ないと思います。アートは10個しかないため、アプリケーションでグループ化できます。ただし、この方法を何千もの芸術で使用しないでください:

     arts = Art.all(:order => "created_at desc", :limit => 10)
     grouped_arts = arts.group_by {|art| art.user_id}
     # now you have a hash with following structure in grouped_arts
     # { 
     #    user_id1 => [art1, art4],
     #    user_id2 => [art3],
     #    user_id3 => [art5],
     #    ....
     # }
    

    編集: latest_artsを選択しますが、ユーザーごとに1つのアートのみを選択します

    sqlのアイデアを提供するためだけに(システムにRDBMSがインストールされていないため、テストしていません)

    SELECT arts.* FROM arts
    WHERE (arts.user_id, arts.created_at) IN 
      (SELECT user_id, MAX(created_at) FROM arts
         GROUP BY user_id
         ORDER BY MAX(created_at) DESC
         LIMIT 10)
    ORDER BY created_at DESC
    LIMIT 10
    

    このソリューションは、同じユーザーの2つのアートが同じ最高のcreated_atを持つことはできないという実際的な仮定に基づいていますが、大量のアートをインポートまたはプログラムで作成している場合は間違っている可能性があります。仮定が当てはまらない場合は、SQLがさらに工夫される可能性があります。

    編集: クエリをArelに変更してみてください:

    Art.where("(arts.user_id, arts.created_at) IN 
                 (SELECT user_id, MAX(created_at) FROM arts
                    GROUP BY user_id
                    ORDER BY MAX(created_at) DESC
                    LIMIT 10)").
        order("created_at DESC").
        page(params[:page]).
        per(params[:per])
    


    1. パラメータ値を文字列からInt32に変換できませんでした

    2. mysqlデータを使用した高低価格での並べ替え

    3. PostgreSQLJDBCを使用した接続プール

    4. EF CoreのPostgreSQLの列の正規表現を一致させる方法は?