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

GROUP BY+CASEステートメント

    名前の競合が発生したり、出力列を混乱させたりする場合を除いて、クエリはすでに機能します。 ( CASE 式)ソース列 結果 、内容が異なります。

    ...
    GROUP BY model.name, attempt.type, attempt.result
    ...

    GROUP BYする必要があります あなたのCASE ソース列の代わりに式:

    ...
    GROUP BY model.name, attempt.type
           , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
    ...

    または、列エイリアスを指定します これは、 FROMの列名とは異なります。 リスト-または、その列が優先されます:

    SELECT ...
         , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
    ...
    GROUP BY model.name, attempt.type, result1
    ...

    SQL標準は、この点でかなり独特です。ここでマニュアルを引用する:

    出力列の名前を使用して、 ORDER BYの列の値を参照できます。 およびGROUPBY 句はありますが、 WHEREにはありません またはHAVING 句;代わりに式を書き出す必要があります。

    そして:

    ORDER BYの場合 式は、出力列名と入力列名の両方に一致する単純な名前、 ORDER BY これを出力列名として解釈します。 これは、 GROUP BYの選択の反対です。 作る 同じ状況で。この不整合は、SQL標準と互換性があるように作成されています。

    太字 強調鉱山。

    これらの競合は、位置参照を使用することで回避できます。 (序数) GROUP BY およびORDERBY SELECT内のアイテムを参照する 左から右にリストします。以下の解決策を参照してください。
    欠点は、これが読みにくく、 SELECTでの編集に対して脆弱である可能性があることです。 リスト(それに応じて位置参照を適応させるのを忘れるかもしれません)。

    しかし、あなたはしません day列を追加する必要があります GROUP BYへ 定数値( CURRENT_DATE-1 を保持している限り) 。

    適切なJOIN構文と位置参照を使用して書き直し、簡略化すると、次のようになります。

    SELECT m.name
         , a.type
         , CASE WHEN a.result = 0 THEN 0 ELSE 1 END AS result
         , CURRENT_DATE - 1 AS day
         , count(*) AS ct
    FROM   attempt    a
    JOIN   prod_hw_id p USING (hard_id)
    JOIN   model      m USING (model_id)
    WHERE  ts >= '2013-11-06 00:00:00'  
    AND    ts <  '2013-11-07 00:00:00'
    GROUP  BY 1,2,3
    ORDER  BY 1,2,3;

    また、列名 timeを避けていることにも注意してください。 。これは予約語であり、識別子として使用しないでください。その上、あなたの「時間」は明らかにタイムスタンプです またはdate 、それはかなり誤解を招く恐れがあります。



    1. Djangoの一意のモデルフィールドと大文字と小文字の区別(postgres)

    2. SQLServerの上位100レコードを更新するにはどうすればよいですか

    3. PostgreSQLテーブルのIDのシーケンスをリセットする方法

    4. Oracleで主キーを持つ重複行を見つける11の方法