简体   繁体   中英

What is the better way to perform inner self join using SQL?

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.

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';

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 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM