PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Избиране на множество max() стойности с помощта на един SQL израз

Още веднъж, за повече от само няколко "типове данни", предлагам да използвате 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)

Връща:

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

Още обяснение за основите:
PostgreSQL Crosstab Query

Динамично решение

Трудното е да направите това напълно динамично :за да работи за

  • неизвестен номер от колони (в този случай типове_данни)
  • с неизвестни имена (отново типове_данни)

Поне тип е добре известно:integer в този случай.

Накратко:това не е възможно с текущия PostgreSQL (включително 9.3). Има приближения с полиморфни типове и начини за заобикаляне на ограниченията с масиви или типове hstore. Може да е достатъчно добро за вас. Но това категорично не е възможно за да получите резултата с отделни колони в една SQL заявка. SQL е много твърд по отношение на типовете и иска да знае какво да очаква обратно.

Въпреки това , може да се направи с два запитвания. Първият изгражда действителната заявка за използване. Въз основа на горния прост случай:

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

Това генерира заявката, от която всъщност се нуждаете. Изпълнете втория в същата транзакция за да избегнете проблеми с едновременността.

Обърнете внимание на стратегическото използване на quote_literal() и quote_ident() за дезинфекция на всички видове незаконни (за колони) имена и предотвратяване на SQL инжектиране .

Не се обърквайте от няколко слоя цитиране на долари. Това е необходимо за изграждане на динамични заявки. Казах го възможно най-просто.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да прехвърля низ към цяло число и да имам 0 в случай на грешка при прехвърлянето с PostgreSQL?

  2. Не може да се свърже с локалния PostgreSQL

  3. Изберете отключен ред в Postgresql

  4. Как да ускорите производителността на вмъкване в PostgreSQL

  5. postgres:надстройване на потребител до суперпотребител?