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

PostgreSQL-条件が成立する行のcount(*)を選択します

    オリジナルを基に構築

    元のクエリは、問題のある行を除外するために正しい方向に進んでいました。 >がありました =の代わりに 。数えるためのトリッキーなステップがありませんでした。

    SELECT count(*) AS ct
    FROM  (
       SELECT 1
       FROM   compatibility c
       WHERE  rating_id = 1
       AND    NOT EXISTS (
          SELECT 1
          FROM   compatibility c2
          WHERE  c2.rating_id > 1
          AND   (c2.attr1_id = c.attr1_id AND c2.attr2_id = c.attr2_id OR
                 c2.attr1_id = c.attr2_id AND c2.attr2_id = c.attr1_id))
       GROUP  BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
       ) sub;
    

    短い

    おそらくもっと速いでしょう。

    SELECT count(*) AS ct
    FROM  (
       SELECT 1  -- selecting more columns for count only would be a waste
       FROM   compatibility
       GROUP  BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
       HAVING every(rating_id = 1)
       ) sub;
    

    @Clodoaldoのクエリ に似ています または、この以前の回答と詳細な説明
    every(rating_id = 1) not bool_or(rating_id > 1)よりも単純です 、ただし、rating < 1も除外します -これはおそらくあなたのケースには問題ありません(またはそれ以上です)。

    MySQL 現在、(標準SQL!)every()を実装していません。 。 rating_id > 1のみを削除したいので 、この単純な式は要件により厳密に適合し、両方のRDBMSで機能します:

    HAVING max(rating_id) = 1
    

    最短

    count(*)を使用 ウィンドウ集計関数として、サブクエリなし。

    SELECT count(*) OVER () AS ct
    FROM   compatibility
    GROUP  BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
    HAVING max(rating_id) = 1
    LIMIT  1;
    

    ウィンドウ関数はに適用されます 集約ステップ。これに基づいて、2つを取得します。 単一のクエリレベルで実行される集計ステップ:

    1. 同等の(atr1_id, atr2_id)を折ります 、発散するrating_idの行を除く 存在します。
    2. セット全体でウィンドウ関数を使用して残りの行をカウントします。

    LIMIT 1 単一の行を取得します(すべての行は同一になります)。
    MySQLにはウィンドウ関数がありません。 Postgres のみ。
    最短、必ずしも最速とは限りません。

    SQLフィドル。 (pg9.3は現在オフラインであるためpg9.2上)



    1. MySQLクエリはphpmyadminで機能しますが、phpでは機能しません

    2. Oracle SQLテーブルへのRデータフレーム:メモリを割り当てることができませんでした

    3. Mysqlを使用して中央値を計算する

    4. カンマ区切りのリストを値と照合するにはどうすればよいですか?