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

PostgreSQLのORDERBY...USING句

    非常に簡単な例は次のとおりです。

    > SELECT * FROM tab ORDER BY col USING <
    

    しかし、これは退屈です。これは、従来のORDER BY col ASCでは得られないものだからです。 。

    また、標準カタログには、奇妙な比較関数/演算子についてエキサイティングなことは何も記載されていません。それらのリストを取得できます:

        > SELECT amoplefttype::regtype, amoprighttype::regtype, amopopr::regoper 
          FROM pg_am JOIN pg_amop ON pg_am.oid = pg_amop.amopmethod 
          WHERE amname = 'btree' AND amopstrategy IN (1,5);
    

    ほとんどの場合、<があることに気付くでしょう。 および> integerのようなプリミティブ型の関数 、date など、配列やベクトルなどの場合はさらにいくつか。これらの演算子はいずれも、カスタム注文を取得するのに役立ちません。

    ほとんど カスタムオーダーが必要な場合は、... ORDER BY somefunc(tablecolumn) ...のようなものを使用して回避できます。 ここで、somefunc 値を適切にマップします。これはすべてのデータベースで機能するため、これも最も一般的な方法です。簡単なことについては、カスタム関数の代わりに式を書くこともできます。

    ギアを切り替える

    ORDER BY ... USING いくつかの場合に意味があります:

    • 順序は非常に珍しいため、somefunc トリックは機能しません。
    • 非プリミティブ型(pointなど)を使用している 、circle または虚数)、奇妙な計算でクエリを繰り返したくない場合。
    • 並べ替えるデータセットが非常に大きいため、インデックスによるサポートが必要であるか、必要でさえあります。

    複雑なデータ型に焦点を当てます。多くの場合、合理的な方法でそれらを並べ替える方法は複数あります。良い例はpointです :(0,0)までの距離、または xで「並べ替え」ることができます 最初に、次に y またはy または他に必要なもの。

    もちろん、PostgreSQLは pointの事前定義された演算子 :

        > CREATE TABLE p ( p point );
        > SELECT p <-> point(0,0) FROM p;
    

    しかし、なし そのうちのORDER BYで使用可能と宣言されています デフォルト(上記を参照):

        > SELECT * FROM p ORDER BY p;
        ERROR:  could not identify an ordering operator for type point
        TIP:  Use an explicit ordering operator or modify the query.
    

    pointの単純な演算子 「下」と「上」の演算子です<^ および>^ 。単純にyを比較します ポイントの一部。しかし:

        >  SELECT * FROM p ORDER BY p USING >^;
        ERROR: operator > is not a valid ordering operator
        TIP: Ordering operators must be "<" or ">" members of __btree__ operator families.
    

    ORDER BY USING セマンティクスが定義された演算子が必要です。明らかに、二項演算子である必要があり、引数と同じ型を受け入れ、ブール値を返す必要があります。また、推移的である必要があると思います(a btreeにも必要です。 -インデックスの順序。これは、 btreeへの参照を含む奇妙なエラーメッセージを説明しています 。

    ORDER BY USING また、1人のオペレーターだけでなく、 定義する必要がありますが、演算子クラス およびオペレーターファミリー 。 1つはできた 1つの演算子のみで並べ替えを実装すると、PostgreSQLは効率的に並べ替えを行い、比較を最小限に抑えようとします。したがって、1つだけを指定した場合でも、いくつかの演算子が使用されます。他の演算子は特定の数学的制約に準拠する必要があります。推移性についてはすでに説明しましたが、他にもあります。

    ギアを切り替える

    適切なものを定義しましょう:yのみを比較するポイントの演算子 一部。

    最初のステップは、 btreeで使用できるカスタム演算子ファミリーを作成することです。 インデックスアクセス方式。参照

        > CREATE OPERATOR FAMILY xyzfam USING btree;   -- superuser access required!
        CREATE OPERATOR FAMILY
    

    次に、2点を比較するときに-1、0、+1を返すコンパレータ関数を提供する必要があります。この関数は 内部で呼び出されます!

        > CREATE FUNCTION xyz_v_cmp(p1 point, p2 point) RETURNS int 
          AS $$BEGIN RETURN btfloat8cmp(p1[1],p2[1]); END $$ LANGUAGE plpgsql;
        CREATE FUNCTION
    

    次に、ファミリの演算子クラスを定義します。番号の説明については、マニュアルを参照してください。

        > CREATE OPERATOR CLASS xyz_ops FOR TYPE point USING btree FAMILY xyzfam AS 
            OPERATOR 1 <^ ,
            OPERATOR 3 ?- ,
            OPERATOR 5 >^ ,
            FUNCTION 1 xyz_v_cmp(point, point) ;
        CREATE OPERATOR CLASS
    

    このステップでは、いくつかの演算子と関数を組み合わせ、それらの関係と意味も定義します。例:OPERATOR 1 意味:これはless-thanの演算子です テスト。

    ここで、演算子<^ および>^ ORDER BY USINGで使用できます :

    > INSERT INTO p SELECT point(floor(random()*100), floor(random()*100)) FROM generate_series(1, 5);
    INSERT 0 5
    > SELECT * FROM p ORDER BY p USING >^;
        p    
    ---------
     (17,8)
     (74,57)
     (59,65)
     (0,87)
     (58,91)
    

    出来上がり-yでソート 。

    要約すると: ORDER BY ... USING PostgreSQLの内部で興味深い外観です。ただし、非常にで作業しない限り、すぐに必要なものは何もありません。 データベーステクノロジーの特定の分野。

    別の例は、Postgresのドキュメントにあります。こことここの例のソースコードを使用します。この例は、演算子を作成する方法も示しています。



    1. MariaDBクラスター10.4の新機能

    2. MySQLまたはMariaDBGaleraClusterを使用したCamundaBPMのデータベースの高可用性

    3. PostgreSQLでのRandom()のしくみ

    4. NOT IN、OUTER APPLY、LEFT OUTER JOIN、EXCEPT、またはNOT EXISTSを使用する必要がありますか?