postgresql同一个表求不同条件的交集?

数据库是postgresql。表table分别有A,B,C,D几个区间的条件数据,
1、求A-B的交集?
2、求A-C的交集,且不在B区间内的?
3、求A-D交集,且不在B-C内的?

当前使用查询语句: select a.name from (select distinct name from table where A) as a join (select distinct name from table where B) as b on a.name = b.name

数据量大约6000W左右,目前是使用子查询然后Join的方式查询。但是查询时间比较长,是否有其他更好的方案?

====实际业务=====
一张订单表,查询某个日期前30天或60天(一个周期)有订单的用户。
需求1、并且在30-60天(前一个周期)有订单
需求2、在30-60天(前一个周期)无订单,在60-90有订单(前2个周期)

阅读 3k
1 个回答

说一下我的优化思路吧
首先用根据时段的分区表(当然要根据的你的业务需求,这样可以节省你查询子表过滤的时间),例如下面的例子是按月分区表

CREATE SCHEMA IF NOT EXISTS log;

DROP TABLE IF EXISTS log.t_log CASCADE;
CREATE TABLE log.t_log (
    name character varying(30),
    time TIMESTAMP WITHOUT TIME ZONE,
    note TEXT
);


CREATE OR REPLACE FUNCTION log.partition_trigger() RETURNS TRIGGER AS $$
DECLARE
    data_text TEXT;
    insert_statement TEXT;
BEGIN
    SELECT TO_CHAR(NEW.time, 'YYYYMM') INTO data_text;
    insert_statement := 'INSERT INTO log.t_log_'||data_text||' VALUES($1.*)';
    EXECUTE insert_statement USING NEW;
    RETURN NULL;
    EXCEPTION
    WHEN UNDEFINED_TABLE
    THEN
        EXECUTE 'CREATE TABLE IF NOT EXISTS log.t_log_'||data_text
        ||'(CHECK (TO_CHAR(time,''YYYYMM'')='''||data_text||''')) INHERITS (log.t_log)';
        RAISE NOTICE 'CREATE NON-EXISTANT TABLE log.t_log_%', data_text;
        EXECUTE 'CREATE INDEX t_log_index_'||data_text||' ON log.t_log_'||data_text||'(time)';
        EXECUTE insert_statement USING NEW;
    RETURN NULL;
END;
$$ LANGUAGE PLPGSQL;


CREATE TRIGGER insert_log_partition_trigger BEFORE INSERT ON log.t_log
FOR EACH ROW EXECUTE PROCEDURE log.partition_trigger();

然后通过子表间的join查询,如果跨多个子表可以直接查询主表并条件过滤

====实际业务=====

看到你的实际业务,优化思路变为每日0时生成30天~60天,60天~90天物化视图(前提你不会补充过去的数据,相当于提前查出两张表,节约查询时间)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题