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

Làm thế nào để trả về kết quả của một SELECT bên trong một hàm trong PostgreSQL?

Sử dụng RETURN QUERY :

CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
  RETURNS TABLE (txt   text   -- also visible as OUT parameter inside function
               , cnt   bigint
               , ratio bigint)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT t.txt
        , count(*) AS cnt                 -- column alias only visible inside
        , (count(*) * 100) / _max_tokens  -- I added brackets
   FROM  (
      SELECT t.txt
      FROM   token t
      WHERE  t.chartype = 'ALPHABETIC'
      LIMIT  _max_tokens
      ) t
   GROUP  BY t.txt
   ORDER  BY cnt DESC;                    -- potential ambiguity 
END
$func$;

Gọi:

SELECT * FROM word_frequency(123);

Xác định kiểu trả về một cách rõ ràng là nhiều thiết thực hơn là trả về một record chung chung . Bằng cách này, bạn không phải cung cấp danh sách định nghĩa cột với mọi lệnh gọi hàm. RETURNS TABLE là một cách để làm điều đó. Co nhung nguoi khac. Các kiểu dữ liệu của OUT các tham số phải khớp chính xác với những gì được trả về bởi truy vấn.

Chọn tên cho OUT các thông số một cách cẩn thận. Chúng có thể nhìn thấy trong phần thân chức năng ở hầu hết mọi nơi. Bảng phân loại các cột có cùng tên để tránh xung đột hoặc kết quả không mong muốn. Tôi đã làm điều đó cho tất cả các cột trong ví dụ của mình.

Nhưng lưu ý rằng xung đột đặt tên có thể xảy ra giữa OUT tham số cnt và bí danh cột cùng tên. Trong trường hợp cụ thể này (RETURN QUERY SELECT ... ) Postgres sử dụng bí danh cột trên OUT tham số theo một trong hai cách. Tuy nhiên, điều này có thể không rõ ràng trong các ngữ cảnh khác. Có nhiều cách khác nhau để tránh bất kỳ sự nhầm lẫn nào:

  1. Sử dụng vị trí thứ tự của mục trong danh sách CHỌN:ORDER BY 2 DESC . Ví dụ:
    • Chọn hàng đầu tiên trong mỗi GROUP BY nhóm?
  2. Lặp lại biểu thức ORDER BY count(*) .
  3. (Không áp dụng ở đây.) Đặt tham số cấu hình plpgsql.variable_conflict hoặc sử dụng lệnh đặc biệt #variable_conflict error | use_variable | use_column trong hàm. Xem:
    • Xung đột đặt tên giữa tham số hàm và kết quả của mệnh đề JOIN với USING

Không sử dụng "văn bản" hoặc "đếm" làm tên cột. Cả hai đều hợp pháp để sử dụng trong Postgres, nhưng "count" là một từ dành riêng trong SQL tiêu chuẩn và một tên hàm cơ bản và "văn bản" là một kiểu dữ liệu cơ bản. Có thể dẫn đến những lỗi khó hiểu. Tôi sử dụng txtcnt trong các ví dụ của tôi, bạn có thể muốn các tên rõ ràng hơn.

Đã thêm một ; bị thiếu và sửa lỗi cú pháp trong tiêu đề. (_max_tokens int) , không phải (int maxTokens) - loại sau tên .

Trong khi làm việc với phép chia số nguyên, tốt hơn nên nhân trước và chia sau, để giảm thiểu lỗi làm tròn. Hoặc làm việc với numeric hoặc một loại dấu chấm động. Xem bên dưới.

Thay thế

Đây là những gì tôi nghĩ truy vấn của bạn thực sự sẽ trông như thế nào (tính toán chia sẻ tương đối trên mỗi mã thông báo ):

CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
  RETURNS TABLE (txt            text
               , abs_cnt        bigint
               , relative_share numeric)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT t.txt, t.cnt
        , round((t.cnt * 100) / (sum(t.cnt) OVER ()), 2)  -- AS relative_share
   FROM  (
      SELECT t.txt, count(*) AS cnt
      FROM   token t
      WHERE  t.chartype = 'ALPHABETIC'
      GROUP  BY t.txt
      ORDER  BY cnt DESC
      LIMIT  _max_tokens
      ) t
   ORDER  BY t.cnt DESC;
END
$func$;

Biểu thức sum(t.cnt) OVER () là một chức năng cửa sổ. Bạn có thể sử dụng CTE thay vì truy vấn con. Khá, nhưng truy vấn con thường rẻ hơn trong những trường hợp đơn giản như thế này (hầu hết trước Postgres 12).

RETURN rõ ràng cuối cùng tuyên bố là không bắt buộc (nhưng được phép) khi làm việc với OUT tham số hoặc RETURNS TABLE (sử dụng ẩn OUT tham số).

round() với hai tham số chỉ hoạt động cho numeric các loại. count() trong truy vấn con tạo ra một bigint kết quả và một sum() qua bigint này tạo ra một numeric kết quả, do đó chúng tôi xử lý một numeric đánh số tự động và mọi thứ sẽ vào đúng vị trí.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chỉ trả về các giá trị số từ một cột cơ sở dữ liệu PostgreSQL

  2. Cách cài đặt PostgreSQL 12 trên Fedora 33

  3. Sử dụng JSONB trong PostgreSQL:Cách lưu trữ &lập chỉ mục hiệu quả dữ liệu JSON trong PostgreSQL

  4. Xây dựng cơ sở dữ liệu khả dụng cao cho Moodle bằng PostgreSQL

  5. Sắp xếp chữ và số với PostgreSQL