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

Вземете редове за последните 10 дати

Това не изглежда подозрително, но е дяволски въпрос .

Предположения

crosstab() заявки

За да получите максимална производителност и кратки низове на заявки (особено ако изпълнявате тази заявка често), предлагам допълнителния модул tablefunc осигуряване на различни crosstab() функции. Основни инструкции:

Основни заявки

Първо трябва да ги направите правилно.

Последните 10 дни:

SELECT DISTINCT date
FROM   book
WHERE  sid = 1
ORDER  BY date DESC
LIMIT  10;

Числа за последните 10 дни с помощта на прозоречната функция dense_rank() :

SELECT *
FROM  (
   SELECT name
        , dense_rank() OVER (ORDER BY date DESC) AS date_rnk
        , count
   FROM   book
   WHERE  sid = 1
   ) sub
WHERE  date_rnk < 11
ORDER  BY name, date_rnk DESC;

(Без включването на действителни дати в тази заявка.)

Имена на колони за изходни колони (за пълно решение):

SELECT 'bookname, "' || string_agg(to_char(date, 'DD/MM/YYYY'), '", "' ORDER BY date) || '"'
FROM  (
   SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY date DESC
   LIMIT  10
   ) sub;

Прост резултат със статични имена на колони

Това може да е достатъчно за вас, но не виждаме действителни дати в резултата:

SELECT * FROM crosstab(
  'SELECT *
   FROM  (
      SELECT name
           , dense_rank() OVER (ORDER BY date DESC) AS date_rnk
           , count
      FROM   book
      WHERE  sid = 1
      ) sub
   WHERE  date_rnk < 11
   ORDER  BY name, date_rnk DESC'
, 'SELECT generate_series(10, 1, -1)'
 ) AS (bookname text
     , date1 int, date2 int, date3 int, date4 int, date5 int
     , date6 int, date7 int, date8 int, date9 int, date10 int);

За многократна употреба ви предлагам да създадете тази (много бърза) обща C функция за 10 цели колони веднъж, за да опростите малко нещата:

CREATE OR REPLACE FUNCTION crosstab_int10(text, text)
  RETURNS TABLE (bookname text
               , date1 int, date2 int, date3 int, date4 int, date5 int
               , date6 int, date7 int, date8 int, date9 int, date10 int)
  LANGUAGE C STABLE STRICT AS
'$libdir/tablefunc','crosstab_hash';

Подробности в този свързан отговор:

Тогава вашето обаждане става:

SELECT * FROM crosstab(
  'SELECT *
   FROM  (
      SELECT name
           , dense_rank() OVER (ORDER BY date DESC) AS date_rnk
           , count
      FROM   book
      WHERE  sid = 1
      ) sub
   WHERE  date_rnk < 11
   ORDER  BY name, date_rnk DESC'
, 'SELECT generate_series(10, 1, -1)'
 );  -- no column definition list required!

Пълно решение с динамични имена на колони

Действителният ви въпрос е по-сложен, вие също искате динамични имена на колони.
За дадена таблица получената заявка може да изглежда така:

SELECT * FROM crosstab_int10(
  'SELECT *
   FROM  (
      SELECT name
           , dense_rank() OVER (ORDER BY date DESC) AS date_rnk
           , count
      FROM   book
      WHERE  sid = 1
      ) sub
   WHERE  date_rnk < 11
   ORDER  BY name, date_rnk DESC'
, 'SELECT generate_series(10, 1, -1)'
   ) AS t(bookname
        , "04/11/2015", "05/11/2015", "06/11/2015", "07/11/2015", "08/11/2015"
        , "09/11/2015", "10/11/2015", "11/11/2015", "15/11/2015", "17/11/2015");

Трудността е да се дестилират имена на динамични колони. Или сглобете низа на заявката на ръка, или (по-скоро) оставете тази функция да го направи вместо вас:

CREATE OR REPLACE FUNCTION f_generate_date10_sql(_sid int = 1) 
  RETURNS text
  LANGUAGE sql AS
$func$
SELECT format(
 $$SELECT * FROM crosstab_int10(
  'SELECT *
   FROM  (
      SELECT name
           , dense_rank() OVER (ORDER BY date DESC) AS date_rnk
           , count
      FROM   book
      WHERE  sid = %1$s
      ) sub
   WHERE  date_rnk < 11
   ORDER  BY name, date_rnk DESC'
, 'SELECT generate_series(10, 1, -1)'
   ) AS ct(bookname, "$$
|| string_agg(to_char(date, 'DD/MM/YYYY'), '", "' ORDER BY date) || '")'
 , _sid)
FROM  (
   SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY date DESC
   LIMIT  10
   ) sub
$func$;

Обаждане:

SELECT f_generate_date10_sql(1);

Това генерира желаната заявка , които изпълнявате на свой ред.

db<>fiddle тук




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. GORM създава запис, който може вече да съществува

  2. Защо всички бази данни имат публична схема в PostgreSQL?

  3. Връща данни от подизбор, използван в INSERT в израз на обща таблица

  4. Rails 3 игнорира изключение за уникално ограничение на Postgres

  5. Django и PostgreSQL последователност за автоматично увеличаване на първичния ключ