En av de nya funktionerna i PostgreSQL 13 är SQL-standarden WITH TIES
sats att använda med LIMIT
— eller, som standarden kallar det, FETCH FIRST n ROWS
. Tack till Surafel Temesgen som första patchförfattare; Tomas Vondra och dina för några ytterligare kodfixar; och recensenterna Andrew Gierth och Erik Rijkers. Du kan läsa commit-meddelandet.
Slipsar är väldigt ofta när man rangordnar saker; till exempel, i ett caucus-lopp kan du ha många oavgjorte, och du vill absolut inte beröva deltagarna deras priser! Vad WITH TIES
gör är ganska enkelt:det lägger till alla följande rader eller rader till din resultatuppsättning, om de rankas lika med den sista raden som returneras enligt LIMIT
klausul, enligt ORDER BY
klausul.
Om du bara vill ha de två anställda med högst lön kan du göra så här:
SELECT * FROM employees ORDER BY salary DESC LIMIT 2;
namn | lön | avdelning |
---|---|---|
Alicia | 1600 | teknik |
Oruga | 1500 | marknadsföring |
Så längtar du efter att veta nästa persons lön? Tänk om hon matchar Oruga och bara utelämnas av en ren slump eller otur? Det kan hända, som du väl vet; och lyckligtvis, WITH TIES
är nu där för att rädda dagen. (Observera att vi i verkligheten inte hanterar WITH TIES
i LIMIT
klausul som sådan. Du måste använda FETCH FIRST
syntax, som är den standardiserade, för att kunna använda WITH TIES
.)
SELECT * FROM employees ORDER BY salary DESC FETCH FIRST 2 ROWS WITH TIES;
namn | lön | avdelning |
---|---|---|
Alicia | 1600 | teknik |
Oruga | 1500 | försäljning |
Conejo Blanco | 1500 | marknadsföring |
Där! White Rabbit hade ska listas, och nu är han det.
Ett par anteckningar innan du blir för arg. LIMIT
(eller mer exakt FETCH FIRST
) lovar inte längre att returnera exakt det antal rader du anger. Du kan få två eller tjugo ytterligare rader, eller 100x så många rader som du bad om. Detta innebär bland annat att du måste hålla reda på hur många rader du har sett hittills, om du paginerar resultat. I ovanstående fick du tre rader, så för nästa sida hoppar du över så många genom att lägga till rätt OFFSET
klausul:
SELECT * FROM employees
ORDER BY salary DESC
FETCH FIRST 2 ROWS WITH TIES
OFFSET 3;
namn | lön | avdelning |
---|---|---|
Falsa Tortuga | 1400 | marknadsföring |
Duquesa | 1300 | försäljning |
Liebre de Marzo | 1300 | teknik |
Vi fick återigen tre snarare än bara två vi bad om. Så för nästa sida måste du hoppa över sex. Och så vidare. Se till att ha tillräckligt med fingerborg för alla.
En annan sak att tänka på är att du måste se till att endast använda ORDER BY
sats som passar WITH TIES
klausul; om du till exempel vill ha raderna med samma lön ordnade efter namn, måste du använda en underfråga. Annars skulle skillnaden i namn lösa lönejämningen, så nästa rad skulle inte ingå. Till exempel:
SELECT * FROM (
SELECT * FROM employees
ORDER BY salary DESC
FETCH FIRST 2 ROWS WITH TIES) AS subq
ORDER BY salary DESC, name;
Den här funktionen är till för att hjälpa dig att visa alla rader som har samma värde – den låter dig inte diskriminera vissa rader med lika värde baserat enbart på fysisk plats i tabellen.
Lycka till med pagineringen!