'SQL to build a list using either EXIST (or NOT EXIST) or a combination of both

I want to find the list of COMPANYID/USERID combos on the USER table that have at least 1 Account found on the ACCOUNT table, but all Accounts are closed. (If there are no Accounts (on ACCOUNT) for the CompanyID/UserID (on USER), it should not be in the results). If just one of the Accounts for a CompanyID/UserID (on USER) is OPEN (on the ACCOUNT table), the CompanyID/UserID should not be on the list.

In the example below, ABC/USER3 is the only combo that fits this. It has 2 accounts (333 & 666) and both are closed. The rest of the CompanyID/UserID combinations have least 1 ACCOUNT that is OPEN. DDD/USER5 is excluded because 888 is not on the ACCOUNT table.

TABLE: USERS

COMPANYID USERID ACCOUNT
AAA USER1 111
AAA USER1 333
ABB USER2 333
ABB USER2 444
ABC USER3 333
ABC USER3 666
BBB USER4 555
CCC USER4 666
DDD USER5 888

TABLE: ACCOUNT

ACCOUNT STATUS
111 OPEN
222 OPEN
333 CLOSED
444 OPEN
555 OPEN
666 CLOSED
777 OPEN

I wrote the original question with table names that I thought would make it easier to follow (instead of the actual DB2 tables I am using) NB002.NBTBAUTH (is USERS) NB002.NBTBMF (is ACCOUNT)

This is the SQL I tried to use:

SELECT NB002.NBTBAUTH.*, Q.USERID, Q.CNTOPEN
FROM NB002.NBTBAUTH LEFT JOIN (SELECT NB002.NBTBAUTH.USERID,
COUNT(IF(NB002.NBTBMF.ACCOUNTSTATUS = 'OPEN',1,NULL)) AS CNTOPEN 
FROM USERS INNER JOIN NB002.NBTBMF ON NB002.NBTBAUTH.ACCOUNTID
     = NB002.NBTBMF.ACCOUNTID
GROUP BY USERID) AS Q ON NB002.NBTBAUTH.USERID = Q.USERID
WHERE NOT Q.USERID IS NULL AND Q.CNTOPEN = 0;

Error message:

SQLCODE -104 Illegal Symbol "=".

It is the first = that is causing it. I changed it to a < and got the same message for the <.



Solution 1:[1]

/*
WITH 
  USERS (COMPANYID, USERID, ACCOUNT) AS
(
          SELECT 'AAA', 'USER1', '111' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'AAA', 'USER1', '333' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'ABB', 'USER2', '333' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'ABB', 'USER2', '444' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'ABC', 'USER3', '333' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'ABC', 'USER3', '666' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'BBB', 'USER4', '555' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'CCC', 'USER4', '666' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'DDD', 'USER5', '888' FROM SYSIBM.SYSDUMMY1
)
, ACCOUNTS (ACCOUNT, STATUS) AS
(
          SELECT '111', 'OPEN'   FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '222', 'OPEN'   FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '333', 'CLOSED' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '444', 'OPEN'   FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '555', 'OPEN'   FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '666', 'CLOSED' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT '777', 'OPEN'   FROM SYSIBM.SYSDUMMY1
)
*/
SELECT U.USERID
FROM USERS U
JOIN ACCOUNTS A ON A.ACCOUNT = U.ACCOUNT
GROUP BY U.USERID
HAVING COUNT (1) = COUNT (CASE A.STATUS WHEN 'CLOSED' THEN 1 END)
USERID
USER3

It's not clear what the USER identifier is - if it's USERID or (COMPANYID, USERID). If latter, then add U.COMPANYID into GROUP BY and SELECT.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1