PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Nhận hàng trong 10 ngày qua

Điều này trông có vẻ khó tin, nhưng đó là một câu hỏi quái gở .

Giả định

crosstab () truy vấn

Để có được hiệu suất cao nhất và chuỗi truy vấn ngắn (đặc biệt nếu bạn chạy truy vấn này thường xuyên), tôi đề xuất mô-đun bổ sung tablefunc cung cấp các crosstab () khác nhau chức năng. Hướng dẫn cơ bản:

Truy vấn cơ bản

Trước tiên, bạn cần phải làm đúng những điều này.

10 ngày qua:

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

Các con số trong 10 ngày qua sử dụng hàm window secure_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;

(Không bao gồm ngày thực tế trong truy vấn này.)

Tên cột cho các cột đầu ra (cho giải pháp đầy đủ):

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;

Kết quả đơn giản với tên cột tĩnh

Điều này có thể đủ tốt cho bạn - nhưng chúng tôi không thấy ngày thực tế trong kết quả:

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);

Để sử dụng nhiều lần, tôi khuyên bạn nên tạo hàm C chung (rất nhanh) này cho 10 cột số nguyên một lần, để đơn giản hóa mọi thứ một chút:

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';

Chi tiết trong câu trả lời liên quan này:

Sau đó, cuộc gọi của bạn trở thành:

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!

Giải pháp đầy đủ với tên cột động

Câu hỏi thực tế của bạn phức tạp hơn, bạn cũng muốn có các tên cột động.
Đối với một bảng nhất định, khi đó truy vấn kết quả có thể trông như thế này:

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");

Khó khăn là chắt lọc các tên cột động. Hãy tập hợp chuỗi truy vấn bằng tay hoặc (nhiều hơn là) để hàm này làm việc đó cho bạn:

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$;

Gọi:

SELECT f_generate_date10_sql(1);

Điều này tạo truy vấn mong muốn , mà bạn thực hiện lần lượt.

db <> fiddle tại đây




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách nhận dữ liệu danh sách ngày trong tháng mỗi tháng trong postgresql

  2. Kết xuất và khôi phục PostgreSQL ở múi giờ khác nhau

  3. Cách ghi các truy vấn trong PostgreSQL

  4. Tìm kiếm toàn văn trong Postgres hoặc CouchDB?

  5. Cách đối phó với 'org.postgresql.util.PSQLException:Không có giá trị nào được chỉ định cho tham số 1'?