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

n個のグループ化されたカテゴリを取得し、他のカテゴリを1つに合計します

    特定の難しさ ここ:SELECTに1つ以上の集計関数があるクエリ リストがあり、GROUP BYはありません 句は、行が見つからない場合でも、正確に1つの行を生成します 基になるテーブルにあります。

    WHEREでできることは何もありません その行を抑制する句。 事後にそのような行を除外する必要があります 、つまりHAVING 句、または外部クエリで。

    ドキュメントごと:

    クエリに集計関数呼び出しが含まれているが、GROUP BYが含まれていない場合 句、グループ化は引き続き発生します。結果は単一のグループ行になります(または、単一の行がHAVINGによって削除された場合は、おそらくnorowsになります。 )。 HAVINGが含まれている場合も同様です。 句、aggregatefunction呼び出しまたはGROUP BYがなくても 条項。

    GROUP BYを追加することに注意してください。 定数式のみの句(それ以外の場合は完全に無意味です!)も機能します。 以下の例を参照してください。 しかし、それが何をするのかはほとんど明らかではないので、短く、安く、単純であっても、私はそのトリックを使用したくありません。

    次のクエリには、単一テーブルスキャンのみが必要です。 カウント順に上位7つのカテゴリを返します。場合(および場合のみ )さらに多くのカテゴリがあり、残りは「その他」にまとめられています:

    WITH cte AS (
       SELECT categoryid, count(*) AS data
            , row_number() OVER (ORDER BY count(*) DESC, categoryid) AS rn
       FROM   contents
       GROUP  BY 1
       )
    (  -- parentheses required again
    SELECT categoryid, COALESCE(ca.name, 'Unknown') AS label, data
    FROM   cte
    LEFT   JOIN category ca ON ca.id = cte.categoryid
    WHERE  rn <= 7
    ORDER  BY rn
    )
    UNION ALL
    SELECT NULL, 'Others', sum(data)
    FROM   cte
    WHERE  rn > 7         -- only take the rest
    HAVING count(*) > 0;  -- only if there actually is a rest
    -- or: HAVING  sum(data) > 0
    
    • 複数のカテゴリが7番目と8番目のランクで同じカウントを持つことができる場合は、関係を断ち切る必要があります。私の例では、categoryidが小さいカテゴリ そのようなレースに勝つ。

    • LIMITを含めるには括弧が必要です またはORDER BY UNIONの個々のレッグへの句 クエリ。

    • テーブルcategoryに参加するだけです。 上位7つのカテゴリ。また、このシナリオでは、最初に集約して後で参加する方が一般的に安価です。したがって、cteという名前のCTE(共通テーブル式)の基本クエリに参加しないでください。 、最初のSELECTにのみ参加します UNIONの クエリ、それは安いです。

    • COALESCEが必要な理由がわからない 。 contents.categoryidの外部キーを使用している場合 category.idへ および両方のcontents.categoryid およびcategory.name NOT NULLで定義されています (おそらくそうあるべきです)、それならあなたはそれを必要としません。

    奇妙なGROUP BY true

    これも機能します:

    ...
    
    UNION ALL
    SELECT NULL , 'Others', sum(data)
    FROM   cte
    WHERE  rn > 7
    GROUP BY true; 

    また、クエリプランが少し速くなります。しかし、それはかなり奇妙なハックです...

    SQLフィドル すべてを示しています。

    UNION ALLの詳細な説明を含む関連回答 / LIMIT テクニック:

    • いくつかのクエリの結果を合計して、SQLで上位5つを見つけます


    1. ORDER BY句は、ビュー、インライン関数、派生テーブル、サブクエリ、および一般的なテーブル式では無効です。

    2. SQL Server:通信リンク障害必要なSSL(パケットの受信に失敗しました)

    3. クエリ以外で使用するとエラーが発生する

    4. EssentialPostgreSQLモニタリング-パート1