PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wybieranie wielu wartości max() za pomocą jednej instrukcji SQL

Jeszcze raz, dla więcej niż tylko kilku "typów danych", sugeruję użycie crosstab() :

SELECT * FROM crosstab(
     $$SELECT DISTINCT ON (1, 2)
              'max' AS "type", data_type, val
       FROM   tbl
       ORDER  BY 1, 2, val DESC$$

    ,$$VALUES ('Final Fantasy'), ('Quake 3'), ('World of Warcraft')$$)
AS x ("type" text, "Final Fantasy" int, "Quake 3" int, "World of Warcraft" int)

Zwroty:

type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max  | 500           | 1500    |    1200

Więcej wyjaśnień podstaw:
Kwerenda krzyżowa PostgreSQL

Rozwiązanie dynamiczne

Trudną rzeczą jest sprawienie, aby to było całkowicie dynamiczne :aby to działało

  • nieznany numer kolumn (w tym przypadku data_types)
  • z nieznanymi nazwami (ponownie data_types)

Przynajmniej typ jest dobrze znany:integer w tym przypadku.

W skrócie:nie jest to możliwe w obecnym PostgreSQL (w tym w wersji 9.3). Istnieją przybliżenia z typami polimorficznymi i sposoby na obejście ograniczeń za pomocą tablic lub typów hstore. Może być dla ciebie wystarczająco dobry. Ale to całkowicie niemożliwe aby uzyskać wynik z pojedynczymi kolumnami w jednym zapytaniu SQL. SQL jest bardzo sztywny co do typów i chce wiedzieć, czego się spodziewać.

Jednak , można to zrobić za pomocą dwóch zapytania. Pierwsza z nich buduje rzeczywiste zapytanie do użycia. Opierając się na powyższym prostym przypadku:

SELECT $f$SELECT * FROM crosstab(
     $$SELECT DISTINCT ON (1, 2)
              'max' AS "type", data_type, val
       FROM   tbl
       ORDER  BY 1, 2, val DESC$$

    ,$$VALUES ($f$     || string_agg(quote_literal(data_type), '), (') || $f$)$$)
AS x ("type" text, $f$ || string_agg(quote_ident(data_type), ' int, ') || ' int)'
FROM  (SELECT DISTINCT data_type FROM tbl) x

To generuje zapytanie, którego faktycznie potrzebujesz. Uruchom drugi w tej samej transakcji aby uniknąć problemów ze współbieżnością.

Zwróć uwagę na strategiczne użycie quote_literal() i quote_ident() do oczyszczania wszelkiego rodzaju niedozwolonych nazw (dla kolumn) i zapobiegania wstrzykiwaniu SQL .

Nie daj się zwieść wielu warstwom kwotowania w dolarach. Jest to niezbędne do tworzenia zapytań dynamicznych. Mówię to tak prosto, jak to tylko możliwe.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego iteracja przez duży Django QuerySet zużywa ogromne ilości pamięci?

  2. Jak mogę uzyskać listę wszystkich funkcji przechowywanych w bazie danych określonego schematu w PostgreSQL?

  3. PostgreSQL - zapytanie ze skryptu bash jako użytkownik bazy danych 'postgres'

  4. Dziesięć sposobów na rozszerzenie funkcjonalności PostgreSQL

  5. Jak używać struktury danych pierścienia w funkcjach okien