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

người dùng được đánh dấu bằng nhãn theo thời gian cho mỗi tháng

Giải pháp của tôi có một số yêu cầu hợp lý, nhưng tôi có thể làm việc mà không cần nó (giá cả là một số hiệu suất).

Tôi đã xây dựng một số bảng trợ giúp những gì được tự động điền bằng trình kích hoạt. Yêu cầu là UPDATE hoặc DELETE không được phép khi truy cập bảng.

mst_user bảng lưu trữ user_id riêng biệt -s và đó là first_visit . user_monthly_visit bảng lưu trữ visit_date cuối cùng và đầu tiên pro user_id tháng .

BẢNG BIỂU

CREATE TABLE mst_user (
  id BIGINT,
  first_visit TIMESTAMP,
  CONSTRAINT pk_mst_user PRIMARY KEY (id)
);

CREATE TABLE visit (
  user_id BIGINT, 
  visit_date TIMESTAMP,
  CONSTRAINT visit_user_fkey FOREIGN KEY (user_id) REFERENCES mst_user (id)
);

CREATE TABLE user_monthly_visit (
  user_id BIGINT,
  month DATE,
  first_visit_this_month TIMESTAMP,
  last_visit_this_month TIMESTAMP,
  CONSTRAINT pk_user_monthly_visit PRIMARY KEY (user_id, month),
  CONSTRAINT user_monthly_visit_user_fkey FOREIGN KEY (user_id) REFERENCES mst_user (id)
);

CREATE INDEX ix_user_monthly_visit_month ON user_monthly_visit(month);

TRIGGER

CREATE OR REPLACE FUNCTION trf_visit()  RETURNS trigger
  VOLATILE
AS $xx$

DECLARE
  l_user_id       BIGINT;
  l_row          RECORD;
  l_user_monthly_visit user_monthly_visit;
BEGIN
  IF (tg_op = 'INSERT')
  THEN
    l_row := NEW;
    INSERT INTO mst_user(id, first_visit) VALUES (l_row.user_id, l_row.visit_date)
    ON CONFLICT(id) DO UPDATE SET first_visit = LEAST(mst_user.first_visit, l_row.visit_date);
    
    INSERT INTO user_monthly_visit(user_id,month,first_visit_this_month,last_visit_this_month) VALUES (l_row.user_id,date_trunc('month',l_row.visit_date),l_row.visit_date,l_row.visit_date) 
    ON CONFLICT(user_id,month) DO UPDATE SET first_visit_this_month = LEAST(user_monthly_visit.first_visit_this_month,l_row.visit_date),
    last_visit_this_month = GREATEST(user_monthly_visit.last_visit_this_month,l_row.visit_date);
  ELSE
    RAISE EXCEPTION 'UPDATE and DELETE arent allowed!';
  END IF;
  RETURN l_row; 
END;
$xx$ LANGUAGE plpgsql;

CREATE TRIGGER trig_visit
  BEFORE INSERT OR DELETE OR UPDATE ON visit
  FOR EACH ROW
  EXECUTE PROCEDURE trf_visit();

DỮ LIỆU THỬ NGHIỆM

INSERT INTO visit (user_id, visit_date)
VALUES (1, '20200101 122915');
INSERT INTO visit (user_id, visit_date)
VALUES (1, '20200102 123011');
INSERT INTO visit (user_id, visit_date)
VALUES (1, '20200401 123101');
INSERT INTO visit (user_id, visit_date)
VALUES (2, '20200501 123114');

QUERY

SELECT mnt AS month, user_id,
CASE WHEN first_visit IS NULL OR first_visit> yyyymm + INTERVAL '1 month' THEN NULL
  WHEN first_visit_this_month = first_visit THEN 'FIRST'
  WHEN first_visit_this_month IS NULL AND last_three_month + INTERVAL '3 month' >= yyyymm THEN 'RETENTION'
  WHEN first_visit_this_month IS NOT NULL THEN 'REACTIVATE'
  ELSE NULL
END user_type
FROM
(SELECT date_part('month', gs.yyyymm)::INTEGER AS mnt, gs.yyyymm, u.id user_id, umv.first_visit_this_month, umv.last_visit_this_month, u.first_visit,
GREATEST(
  LAG(last_visit_this_month) OVER w,
  LAG(last_visit_this_month,2) OVER w,
  LAG(last_visit_this_month,3) OVER w
) last_three_month
FROM 
  generate_series('2020-01-01'::TIMESTAMP, '2020-12-01'::TIMESTAMP, INTERVAL '1 month') gs(yyyymm)
  CROSS JOIN mst_user u
  LEFT JOIN user_monthly_visit umv on (umv.user_id=u.id AND umv.month = gs.yyyymm)
  WINDOW w AS (PARTITION BY u.id ORDER BY gs.yyyymm)  
) monthly_visit
ORDER BY user_id,mnt;

KẾT QUẢ

tháng user_id user_type
1 1 ĐẦU TIÊN
2 1 CHO THUÊ
3 1 CHO THUÊ
4 1 REACTIVATE
5 1 CHO THUÊ
6 1 CHO THUÊ
7 1 CHO THUÊ
8 1 (null)
9 1 (null)
10 1 (null)
11 1 (null)
12 1 (null)
1 2 (null)
2 2 (null)
3 2 (null)
4 2 (null)
5 2 ĐẦU TIÊN
6 2 CHO THUÊ
7 2 CHO THUÊ
8 2 CHO THUÊ
9 2 (null)
10 2 (null)
11 2 (null)
12 2 (null)


  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ó một cột ĐỊA LÝ chung với PostGIS

  2. Cách tìm kiếm trong trường json có chứa một mảng đối tượng bằng Eloquent

  3. Các phần tử truy vấn trong một mảng lồng nhau của một đối tượng json trong postgresql 9.4 hoặc 9.5

  4. Cài đặt PostgreSQL trên Ubuntu 20.04

  5. Postgresql UUID được hỗ trợ bởi Hibernate?