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

Phương pháp mạnh mẽ để xây dựng các truy vấn SQL theo chương trình

Truy vấn tốt hơn

Đối với người mới bắt đầu, bạn có thể sửa cú pháp, đơn giản hóa và làm rõ một chút:

SELECT *
FROM  (
   SELECT p.person_id, p.name, p.team, sum(s.score)::int AS score
         ,rank() OVER (PARTITION BY p.team
                       ORDER BY sum(s.score) DESC)::int AS rnk
    FROM  person p
    JOIN  score  s USING (person_id)
    GROUP BY 1
   ) sub
WHERE  rnk < 3;
  • Xây dựng trên bố cục bảng cập nhật của tôi. Xem fiddle bên dưới.

  • Bạn không cần truy vấn phụ bổ sung. Các chức năng của cửa sổ được thực thi sau tổng hợp các chức năng, vì vậy bạn có thể lồng ghép nó như đã trình bày.

  • Trong khi nói về "xếp hạng", bạn có thể muốn sử dụng rank() , không phải row_number() .

  • Giả sử people.people_id là PK, bạn có thể đơn giản hóa GROUP BY .

  • Đảm bảo xác định bảng đủ điều kiện cho tất cả các tên cột có thể không rõ ràng

Hàm PL / pgSQL

Sau đó, tôi sẽ viết một hàm plpgsql nhận tham số cho các phần biến của bạn. Thực hiện a - c điểm của bạn. d không rõ ràng, để lại cho bạn thêm.

CREATE OR REPLACE FUNCTION f_demo(_agg text       DEFAULT 'sum'
                               , _left_join bool  DEFAULT FALSE
                               , _where_name text DEFAULT NULL)
  RETURNS TABLE(person_id int, name text, team text, score int, rnk int) AS
$func$
DECLARE
   _agg_op  CONSTANT text[] := '{count, sum, avg}';  -- allowed functions
   _sql     text;
BEGIN

-- assert --
IF _agg ILIKE ANY (_agg_op) THEN
   -- all good
ELSE
   RAISE EXCEPTION '_agg must be one of %', _agg_op;
END IF;

-- query --
_sql := format('
SELECT *
FROM  (
   SELECT p.person_id, p.name, p.team, %1$s(s.score)::int AS score
         ,rank() OVER (PARTITION BY p.team
                       ORDER BY %1$s(s.score) DESC)::int AS rnk
    FROM  person p
    %2$s  score  s USING (person_id)
    %3$s
    GROUP BY 1
   ) sub
WHERE  rnk < 3
ORDER  BY team, rnk'
   , _agg
   , CASE WHEN _left_join THEN 'LEFT JOIN' ELSE 'JOIN' END
   , CASE WHEN _where_name <> '' THEN 'WHERE p.name LIKE $1' ELSE '' END
);

-- debug   -- quote when tested ok
-- RAISE NOTICE '%', _sql;

-- execute -- unquote when tested ok
RETURN QUERY EXECUTE _sql
USING  _where_name;   -- $1

END
$func$  LANGUAGE plpgsql;

Gọi:

SELECT * FROM f_demo();
SELECT * FROM f_demo('sum', TRUE, '%2');    
SELECT * FROM f_demo('avg', FALSE);
SELECT * FROM f_demo(_where_name := '%1_'); -- named param

SQL 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. Phát triển vai trò quản trị viên:PG ::Lỗi:ERROR:quản trị viên quan hệ đã tồn tại

  2. @@ Fetch_status trong postgreSQL

  3. Truy vấn SQL để chuyển đổi số lượng cột thành số lượng hàng

  4. Làm cách nào để lấy một mục ngẫu nhiên từ cơ sở dữ liệu trong Django / postgreSQL?

  5. Kiểm tra xem trường có tồn tại trong cột kiểu json PostgreSQL hay không