Reputation: 2388
Is there a way write an optimized version of the self join query I have below? I'm trying to find user chat room session activity of users who have logged out but visited specific chat rooms such as in the sample SQL query below where users who entered chatroom 1 and 3 and have exited.
DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl (
id BIGSERIAL PRIMARY KEY,
empno INT,
activity VARCHAR(50)
);
INSERT INTO tbl (empno, activity) VALUES
(1, 'logged_in'),
(1, 'chatroom1'),
(1, 'chatroom3'),
(2, 'logged_in'),
(2, 'logged_out'),
(1, 'logged_out'),
(3, 'logged_in'),
(3, 'chatroom5');
Select t1.* from
(Select empno, activity from tbl where activity in ('chatroom1', 'chatroom3')) as t1
JOIN
(Select empno from tbl where activity ='logged_out') as t2
ON
t1.empno = t2.empno
I wrote the above script using PostgreSQL but I'm looking for a better way for writing SQL self joins. I guess for Sub queries I could have used CTE.
Upvotes: 2
Views: 70
Reputation: 1270191
You can also use aggregation. If I understand correctly:
select empno
from tbl
group by empno
having sum( (activity = 'logged_out')::int ) > 0 and
sum( (activity = 'chatroom1')::int ) > 0 and
sum( (activity = 'chatroom3')::int ) > 0;
If you mean either chatroom and not both, I would use:
having sum( (activity = 'logged_out')::int ) > 0 and
sum( (activity in ('chatroom1', 'chatroom3') )::int ) > 0
Upvotes: 2
Reputation: 30829
You can use the following query:
SELECT t1.*
FROM tbl t1 JOIN tbl t2 ON t1.empno = t2.empno
WHERE t1.activity IN ('chatroom1', 'chatroom3')
AND t2.activity ='logged_out';
Upvotes: 3