Home > Mobile >  Oracle SQL query SELECT with IN not correctly returning the result
Oracle SQL query SELECT with IN not correctly returning the result

Time:10-13

I have an Oracle query using SELECT and IN.

Below is the table EMPLOYEE data:

INSERT INTO EMPLOYEES (BADGEID, EMP_NAME) VALUES ('10001', 'John');
INSERT INTO EMPLOYEES (BADGEID, EMP_NAME) VALUES ('10002', 'Mark');
INSERT INTO EMPLOYEES (BADGEID, EMP_NAME) VALUES ('10003', 'James');

This one is WRISTRAP data:

INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES ('10001', 'Pass', 'Pass', TO_DATE('13-OCT-2022 13:10:12', 'dd-MON-yyyy hh24:mi:ss'));
INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES ('10001', 'Fail', 'Pass', TO_DATE('13-OCT-2022 13:09:34', 'dd-MON-yyyy hh24:mi:ss'));
INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES ('10001', 'Pass', 'Pass', TO_DATE('13-OCT-2022 13:08:17', 'dd-MON-yyyy hh24:mi:ss'));
INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES('10002', 'Pass', 'Pass', TO_DATE('13-OCT-2022 13:16:22', 'dd-MON-yyyy hh24:mi:ss'));
INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES ('10002', 'Pass', 'Pass', TO_DATE('13-OCT-2022 13:11:25', 'dd-MON-yyyy hh24:mi:ss'));
INSERT INTO WRISTRAP (BADGEID_FK, WRISTRAP, FOOT, DATEADDED) 
VALUES ('10003', 'Pass', 'Fail', TO_DATE('13-OCT-2022 13:21:44', 'dd-MON-yyyy hh24:mi:ss'));

Now I tried to make query to check employee already Wristrap but still get WRISTRAP fail or FOOT fail.

Above data explain that Badge ID 10001 already Wristrap with latest result is All Pass.

This is my SQL query:

SELECT
    E.BADGEID
FROM
    EMPLOYEES E
WHERE
    BADGEID IN (SELECT BADGEID_FK
                FROM WRISTRAP
                WHERE WRISTRAP = 'Fail' OR FOOT = 'Fail')

After execute the query, I still got Badge ID 10001 shown on query data. It should be not there because the latest Wristrap is Pass (Date: 13-OCT-2022 13:10:12).

I also prepare for SQL Fiddle for the demo.

CodePudding user response:

One way to get the values of the last row per badgeid_fk is to group by it and use Oracle's KEEP LAST:

SELECT e.badgeid
FROM employees e
WHERE e.badgeid IN 
(
  SELECT badgeid_fk
  FROM wristrap
  GROUP BY badgeid_fk
  HAVING MAX(wristrap) KEEP (DENSE_RANK LAST ORDER BY dateadded) = 'Fail'
      OR MAX(foot) KEEP (DENSE_RANK LAST ORDER BY dateadded) = 'Fail'
);

One standard-compliant approach would be to use a window function:

WITH latest_wristraps AS
(
  SELECT badgeid_fk, wristrap, foot
  FROM wristrap
  ORDER BY DENSE_RANK() OVER (PARTITION BY badgeid_fk ORDER BY dateadded DESC)
  FETCH FIRST ROW WITH TIES
)
SELECT e.badgeid
FROM employees e
WHERE e.badgeid IN 
(
  SELECT badgeid_fk
  FROM lastest_wristraps
  WHERE wristrap = 'Fail'
  OR foot = 'Fail'
);

CodePudding user response:

I think you should first need to find the latest added date for each BADGE ID and then search for the failed ones. Something like this one should do the trick

 select EMP_NAME, BADGEID from EMPLOYEES,  (
select
  BADGEID_FK,
  WRISTRAP,
  FOOT
FROM
(
  SELECT
    BADGEID_FK,
    WRISTRAP,
    FOOT,
    DATEADDED,
    MAX(DATEADDED) OVER(PARTITION BY BADGEID_FK) as LAST_ADDED_DATE
  FROM
    WRISTRAP  
)
WHERE
  DATEADDED=LAST_ADDED_DATE  )BADGES WHERE   EMPLOYEES.BADGEID=BADGES.BADGEID_FK  AND (BADGES.WRISTRAP = 'Fail' OR BADGES.FOOT = 'Fail')
  • Related