使用子记录最近日期加快搜索日期(postgresql)

时间:2017-09-15 07:52:05

标签: sql postgresql postgresql-9.4

我想找到仍然没有近期活动的旧工作。

表格如下:

CREATE TABLE job
    (jobid int4, jobname text, jobdate date);    
INSERT INTO job
    (jobid, jobname, jobdate)
VALUES
    (1,'X','2016-12-31'),
    (2,'Y','2016-12-31'),
    (3,'Z','2016-12-31');

CREATE TABLE hr
   (hrid int4, hrjob int4, hrdate date);
INSERT INTO hr
   (hrid, hrjob, hrdate)
VALUES
    (1,1,'2017-05-30'),
    (2,1,'2016-12-31'),
    (3,2,'2016-12-31'),
    (4,3,'2016-12-31'),
    (5,4,'2017-12-31');

CREATE TABLE po
    (poid int, pojob int4, podate date);
INSERT INTO po
    (poid, pojob, podate)
VALUES
    (1,1,'2016-05-30'),
    (2,1,'2016-12-31'),
    (3,2,'2016-12-31'),
    (4,3,'2016-12-31'),
    (5,4,'2017-12-31');

我找到了一个适用于少量记录的解决方案,但需要花费很长时间才能完成数千条记录

SELECT    jobid 
FROM      job 
LEFT JOIN hr ON hrjob=jobid 
LEFT JOIN po ON poid=jobid
WHERE     jobdate <'2017-12-31'
GROUP BY  jobid
HAVING    greatest(max(hrdate),max(podate))<'2017-12-31' 
ORDER BY  jobid

有没有办法简化和加快这个查询?

在这种情况下,除了4之外的所有工作都可以关闭=没有最近的活动。

SQLFiddle:http://sqlfiddle.com/#!15/098c3/1

执行计划:

GroupAggregate (cost=311.82..1199.60 rows=67 width=12)
Filter: (GREATEST(max(hr.hrdate), max(po.podate)) < '2017-12-31'::date)
-> Merge Left Join (cost=311.82..925.66 rows=36414 width=12)
Merge Cond: (job.jobid = po.poid)
-> Merge Left Join (cost=176.48..234.72 rows=3754 width=8)
Merge Cond: (job.jobid = hr.hrjob)
-> Sort (cost=41.13..42.10 rows=387 width=4)
Sort Key: job.jobid
-> Seq Scan on job (cost=0.00..24.50 rows=387 width=4)
Filter: (jobdate < '2017-12-31'::date)
-> Sort (cost=135.34..140.19 rows=1940 width=8)
Sort Key: hr.hrjob
-> Seq Scan on hr (cost=0.00..29.40 rows=1940 width=8)
-> Sort (cost=135.34..140.19 rows=1940 width=8)
Sort Key: po.poid
-> Seq Scan on po (cost=0.00..29.40 rows=1940 width=8)

说明:

Output: job.jobid
Filter: (GREATEST(max(hr.hrdate), max(po.podate)) < '2017-12-31'::date)
-> Merge Left Join (cost=311.82..925.66 rows=36414 width=12) (actual time=0.032..0.039 rows=4 loops=1)
Output: job.jobid, hr.hrdate, po.podate
Merge Cond: (job.jobid = po.poid -> Merge Left Join (cost=176.48..234.72 rows=3754 width=8) (actual time=0.024..0.028 rows=4 loops=1)
Output: job.jobid, hr.hrdate
Merge Cond: (job.jobid = hr.hrjob -> Sort (cost=41.13..42.10 rows=387 width=4) (actual time=0.014..0.015 rows=3 loops=1)
Output: job.jobid
Sort Key: job.jobid
Sort Method: quicksort Memory: 25kB -> Seq Scan on public.job (cost=0.00..24.50 rows=387 width=4) (actual time=0.006..0.007 rows=3 loops=1)
Output: job.jobid
Filter: (job.jobdate < '2017-12-31'::date) -> Sort (cost=135.34..140.19 rows=1940 width=8) (actual time=0.008..0.009 rows=5 loops=1)
Output: hr.hrdate, hr.hrjob
Sort Key: hr.hrjob
Sort Method: quicksort Memory: 25kB -> Seq Scan on public.hr (cost=0.00..29.40 rows=1940 width=8) (actual time=0.001..0.002 rows=5 loops=1)
Output: hr.hrdate, hr.hrjob -> Sort (cost=135.34..140.19 rows=1940 width=8) (actual time=0.007..0.007 rows=5 loops=1)
Output: po.podate, po.poid
Sort Key: po.poid
Sort Method: quicksort Memory: 25kB -> Seq Scan on public.po (cost=0.00..29.40 rows=1940 width=8) (actual time=0.001..0.003 rows=5 loops=1)
Output: po.podate, po.poid
Total runtime: 0.148 ms

提前谢谢

2 个答案:

答案 0 :(得分:1)

您可以找到像这样的旧作业

,而不是使用JOIN和GROUP BY
SELECT jobid 
FROM   job 
WHERE  jobdate < '2017-12-31' 
       AND NOT EXISTS (SELECT 1 
                       FROM   hr 
                       WHERE  hr.hrjob = job.jobid 
                              AND hrdate >= '2017-12-31') 
       AND NOT EXISTS (SELECT 1 
                       FROM   po 
                       WHERE  po.poid = job.jobid 
                              AND podate >= '2017-12-31') 
ORDER  BY jobid 

我认为它可以加快您的查询速度。

答案 1 :(得分:0)

可以为您节省大量潜在处理的事情是向作业添加一个字段,指示作业已关闭。这可以为您节省大量的查询工作!