Search code examples
sqlselectrelational-division

select data that has at least P and R


I have a table named Table1 as shown below:

ID  AccountNo     Trn_cd
1   123456           P
2   123456           R
3   123456           P
4   12345            P
5   111              R
6   111              R
7   5625             P

I would like to display those records that accountNo appears more than one time (duplicate) and trn_cd has at least both P and R.

In this case the output should be at this way:

ID  AccountNo     Trn_cd
1   123456           P
2   123456           R
3   123456           P

I have done this sql but not the result i want:

select * from Table1 
where AccountNo IN 
(select accountno from table1 
where trn_cd = 'P' or trn_cd = 'R' 
group by AccountNo having count(*) > 1) 

Result as below which AccountNo 111 shouldn't appear because there is no trn_cd P for 111:

ID  AccountNo   Trn_cd
1   123456        P
2   123456        R
3   123456        P
5   111           R
6   111           R

Any idea?


Solution

  • This problem is called Relational Division.

    This can be solved by filtering the records which contains P and R and counting the records for every AccountNo returned, and filtering it again using COUNT(DISTINCT Trn_CD) = 2.

    SELECT  a.*
    FROM    tableName a
            INNER JOIN
            (
                SELECT  AccountNo
                FROM    TableName
                WHERE   Trn_CD IN ('P','R')
                GROUP   BY AccountNo
                HAVING  COUNT(DISTINCT Trn_CD) = 2
            ) b ON a.AccountNO = b.AccountNo
    

    OUTPUT

    ╔════╦═══════════╦════════╗
    ║ ID ║ ACCOUNTNO ║ TRN_CD ║
    ╠════╬═══════════╬════════╣
    ║  1 ║    123456 ║ P      ║
    ║  2 ║    123456 ║ R      ║
    ║  3 ║    123456 ║ P      ║
    ╚════╩═══════════╩════════╝
    

    For faster performance, add an INDEX on column AccountNo.