Alchemist
Alchemist

Reputation: 869

How to support two conditions in the group by clause (postgresql)

I have three table TableA, TableB, TableC they all are linked by id. Table A has logTime and tableB has detectionTime and TableC has emptId.

For each empId I want 1. count of logTime when no detectionTime found in tableB 2. average of logTime and detectionTime difference if detectionTime found.

I have written this query that gets the average when detectionTime found but not sure how to get data when detectionTime not found

select det.empid  ,average(det.blocked_time) 
FROM (SELECT c.emplid as empid, EXTRACT(EPOCH FROM ( a.detectionTime - b.logTime )) as blocked_time
        ## inner and join condition here
  ) As det group by det.emplid where dat.blocked_time>0

Here I got entry when blocked_time>0 average and other stats.

How to get count of blocked_time for each empId when blocked_time is 0

Upvotes: 0

Views: 64

Answers (3)

G.Arima
G.Arima

Reputation: 1171

Try this out:

select emptid,
sum(case when detectiontime is null then 1 else 0 end) as count,
average(case when detectiontime is not null then diff else 0 end) as avg
(
select a.*,b.detectiontime,c.emptid,a.logtime-b.detectiontime as diff
from
tablea a
left join
tableb b
on a.id = b.id
left join
tablec c
on a.id = c.id
)
group by emptid;

Let me know if you are looking for something else.

Upvotes: 1

Laurenz Albe
Laurenz Albe

Reputation: 246113

First, a few comments:

  • Your. SQL statement is syntactically incorrect. WHERE must come before GROUP BY.

  • Your query seems to assume that id is a unique key for all three tables. Otherwise the same value could appear in the join result multiple times.

The expression you are looking for is

count(blocked_time) FILTER (WHERE blocked_time = 0)

Upvotes: 2

zarruq
zarruq

Reputation: 2465

As no sample data is shared, so an (assumed) option could be to use left join and coalesce in inner query to convert NULL values for detectionTime to 0 and then use conditional aggregation in outer query as below.

select det.empid  ,
       avg(case when detectionTime  > 0 then det.blocked_time end) as avgBlockedTime, 
       sum(case when detectionTime =  0 then 0 else 1 end) as logTimeCount
FROM (SELECT c.emplid as empid, 
      EXTRACT(EPOCH FROM ( a.detectionTime - b.logTime )) as blocked_time,
      coalesce(DetectionTime,0) as detectionTime
      ## left outer join and condition here
  ) As det 
group by det.empid

Upvotes: 1

Related Questions