sql >> Database teknologi >  >> RDS >> PostgreSQL

BESTIL VED ... BRUG af klausul i PostgreSQL

Et meget simpelt eksempel ville være:

> VÆLG * FRA fanen BESTIL VED COMMISSION < 

Men det er kedeligt, for det er ikke noget, du ikke kan få med den traditionelle ORDER BY col ASC .

Standardkataloget nævner heller ikke noget spændende om mærkelige sammenligningsfunktioner/operatorer. Du kan få en liste over dem:

> VÆLG amoplefttype::regtype, amoprighttype::regtype, amopopr::regoper FRA pg_am JOIN pg_amop PÅ pg_am.oid =pg_amop.amopmethod HVOR amname ='btree' OG amopstrategy IN (1,5); 

Du vil bemærke, at der for det meste er < og > funktioner for primitive typer som heltal , dato osv. og nogle flere til arrays og vektorer og så videre. Ingen af ​​disse operatører vil hjælpe dig med at få en tilpasset bestilling.

I de fleste tilfælde, hvor brugerdefineret bestilling er påkrævet, kan du slippe afsted ved at bruge noget som ... BESTIL AF somefunc(tabelkolonne) ... hvor somefunc kortlægger værdierne korrekt. Fordi det fungerer med enhver database, er dette også den mest almindelige måde. For simple ting kan du endda skrive et udtryk i stedet for en brugerdefineret funktion.

Skifter gear

BEstil VED ... BRUG giver mening i flere tilfælde:

  • Bestillingen er så usædvanlig, at somefunc tricket virker ikke.
  • Du arbejder med en ikke-primitiv type (som punkt , cirkel eller imaginære tal), og du ønsker ikke at gentage dig selv i dine forespørgsler med mærkelige beregninger.
  • Det datasæt, du vil sortere, er så stort, at det er ønsket eller endda påkrævet at understøtte et indeks.

Jeg vil fokusere på de komplekse datatyper:ofte er der mere end én måde at sortere dem på på en rimelig måde. Et godt eksempel er point :Du kan "bestille" dem efter afstanden til (0,0) eller ved x først, derefter af y eller bare af y eller noget andet du ønsker.

PostgreSQL har selvfølgelig foruddefinerede operatorer for punkt :

> CREATE TABLE p ( p point );> VÆLG p <-> punkt(0,0) FRA p; 

Men ingen af dem er erklæret brugbare til ORDER BY som standard (se ovenfor):

> VÆLG * FRA p BESTIL AF p; FEJL:kunne ikke identificere en bestillende operator for typepunkt TIP:Brug en eksplicit ordreoperator eller modificer forespørgslen.

Simple operatorer for point er operatorerne "under" og "over" <^ og >^ . De sammenligner simpelthen y en del af pointen. Men:

> VÆLG * FRA p BESTIL VED p BRUGE>^; FEJL:operator> er ikke en gyldig bestillingsoperatør TIP:Bestillingsoperatører skal være "<" eller ">" medlemmer af __btree__ operatørfamilier. 

BEstil ved at bruge kræver en operator med defineret semantik:Det skal selvfølgelig være en binær operator, den skal acceptere den samme type som argumenter og den skal returnere boolesk. Jeg tror, ​​det også skal være transitivt (hvis a btree -indeksbestilling. Dette forklarer de mærkelige fejlmeddelelser, der indeholder referencen til btree .

BEstil ved at bruge kræver heller ikke kun én operatør skal defineres, men en operatørklasse og en operatørfamilie . Mens man kunne implementere sortering med kun én operatør, forsøger PostgreSQL at sortere effektivt og minimere sammenligninger. Derfor bruges flere operatorer, selv når du kun angiver én - de andre skal overholde visse matematiske begrænsninger - jeg har allerede nævnt transitivitet, men der er flere.

Skift gear

Lad os definere noget passende:En operator for punkter, som kun sammenligner y del.

Det første trin er at oprette en brugerdefineret operatørfamilie, som kan bruges af btree indeksadgangsmetode. se

> OPRET OPERATØRFAMILIE xyzfam VED HJÆLP AF btree; -- Superbrugeradgang påkrævet! OPRET OPERATØRFAMILIE 

Dernæst skal vi give en komparatorfunktion, som returnerer -1, 0, +1, når vi sammenligner to punkter. Denne funktion VIL blive ringet op internt!

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

Dernæst definerer vi operatørklassen for familien. Se manualen for en forklaring af tallene.

> OPRET OPERATØRKLASSE xyz_ops FOR TYPEpunkt VED HJÆLP AF btree FAMILY xyzfam SOM OPERATØR 1 <^ , OPERATØR 3 ?- , OPERATØR 5>^ , FUNKTION 1 xyz_v_cmp(punkt, punkt); OPRET OPERATØRKLASSE 

Dette trin kombinerer flere operatorer og funktioner og definerer også deres forhold og betydning. For eksempel OPERATOR 1 betyder:Dette er operatoren for mindre-end tests.

Nu er operatorerne <^ og >^ kan bruges i ORDER BY USING :

> INSERT INTO p SELECT point(floor(random()*100), floor(random()*100)) FROM gener_series(1, 5);INSERT 0 5> SELECT * FROM p BESTIL AF p BRUGER>^; p ---------- (17,8) (74,57) (59,65) (0,87) (58,91)

Voila - sorteret efter y .

For at opsummere det: BEstil VED ... BRUG er et interessant look under hætten på PostgreSQL. Men du vil ikke kræve noget som helst snart, medmindre du arbejder meget specifikke områder inden for databaseteknologi.

Et andet eksempel kan findes i Postgres docs. med kildekode til eksemplet her og her. Dette eksempel viser også, hvordan man opretter operatørerne.



  1. Openshift og net-ssh inkompatibilitet? (2.9.3-beta1 vs. 2.9.2)

  2. Kan ikke VÆLGE fra UPDATE RETURNING-klausulen i postgres

  3. Sådan tilføjes en separator til en sammenkædet streng i MySQL – CONCAT_WS()

  4. Sådan vælger du et kolonnenavn med et mellemrum i MySQL