sql >> Databasteknik >  >> RDS >> PostgreSQL

Varför kan jag inte utesluta beroende kolumner från `GROUP BY` när jag aggregerar med en nyckel?

Eftersom endast PK täcker alla kolumner i en underliggande tabell i GROUP BY klausul. Därför fungerar din första fråga. En UNIQUE begränsning gör det inte.

Kombinationen av en UNIQUE som inte kan uppskjutas och en NOT NULL begränsning skulle också kvalificera sig. Men det är inte implementerat - liksom några andra funktionella beroenden som är kända för SQL-standarden. Peter Eisentraut, huvudförfattaren till inslaget, hade mer i åtanke, men det fastställdes vid den tiden att efterfrågan är låg och associerade kostnader kan vara höga. Se diskussionen om funktionen på pgsql-hackers.

Manualen:

När GROUP BY är närvarande, eller några aggregerade funktioner är närvarande, är det inte giltigt för SELECT listuttryck för att hänvisa till ogrupperade kolumner förutom inom aggregerade funktioner eller när den ogrupperade kolumnen är funktionellt beroende av de grupperade kolumnerna, eftersom det annars skulle finnas mer än ett möjligt värde att returnera för en ogrupperad kolumn. Ett funktionellt beroende existerar om de grupperade kolumnerna (eller en delmängd därav) är den primära nyckeln i tabellen som innehåller den ogrupperade kolumnen.

Och mer explicit:

PostgreSQL känner igen funktionellt beroende (så att kolumner kan utelämnas från GROUP BY ) endast när en tabells primärnyckel ingår i GROUP BY lista. SQL-standarden specificerar ytterligare villkor som bör kännas igen.

Sedan c.vin är UNIQUE NOT NULL , kan du fixa din andra fråga genom att använda kolumnen PK istället:

...
group by c.id;

Bortsett från, medan referensintegritet upprätthålls och hela tabellen efterfrågas, kan båda de givna frågorna vara avsevärt billigare:aggregerade rader i appraisal före sammanfogningen. Detta tar bort behovet av att GROUP BY i den yttre SELECT a priori. Gilla:

SELECT c.vin, c.color, c.brand
     , a.min_appraisal
     , a.max_appraisal
FROM   car c
LEFT   JOIN (
   SELECT car_vin
        , min(price) AS min_appraisal
        , max(price) AS max_appraisal
   FROM   appraisal
   GROUP  BY car_vin
   ) a ON a.car_vin = c.vin;

Se:

  • Flera array_agg()-anrop i en enda fråga

Relaterat:

  • SQL-sats som fungerar i MySQL fungerar inte i Postgresql - Sum &group_by rails 3
  • PostgreSQL - GROUP BY-sats



  1. Kan inte öppna SQLite-databasen från SQLIte Helper Oncreate, när OnCreate utlöses genom att öppna databasen för första gången

  2. Ställ in teckenuppsättningen och sorteringen av en tabell i MariaDB

  3. Konvertera ett datum i MySQL från strängfält

  4. Migrera från Postgres till SQL Server 2008