Home > OS >  MYSQL - Having clause does not return any rows
MYSQL - Having clause does not return any rows

Time:09-19

Student Visa Approval Process

Table: STUDENT_MST

VISA_APPROVED:
    'P': Visa Approval is Pending
    'Y': Visa is Approved
    'N': Visa is not Approved

UNIVERSITY_APPROVED:
    'P': University Approval is Pending
    'Y': University has approved the Student
    'N': University has rejected the Student
STUDENT_MST_ID STUDENT_ID STUDENT_FILE_ID VISA_APPROVED UNIVERSITY_APPROVED
1 'STU-1' 'FILE-1' 'P' 'P'
2 'STU-2' 'FILE-2' 'Y' 'Y'
3 'STU-3' 'FILE-3' 'N' 'N'
4 'STU-3' 'FILE-4' 'Y' 'Y'
5 'STU-4' 'FILE-5' 'N' 'Y'
6 'STU-4' 'FILE-6' 'Y' 'Y'
7 'STU-5' 'FILE-7' 'N' 'Y'
8 'STU-5' 'FILE-8' 'N' 'Y'
9 'STU-5' 'FILE-9' 'Y' 'Y'
Table: FILE_MST

FILE_PROCESSED:
    'N': File not processed
    'Y': File Processed 
FILE_MST_ID STUDENT_FILE_ID FILE_PROCESSED
1 'FILE-1' 'N'
2 'FILE-2' 'Y'
3 'FILE-3' 'N'
4 'FILE-4' 'Y'
5 'FILE-5' 'Y'
6 'FILE-6' 'Y'
7 'FILE-7' 'Y'
8 'FILE-8' 'Y'
9 'FILE-9' 'Y'

I want to fetch all the records where a student has applied more than once [COUNT(studntMst.STUDENT_ID) > 1] and only their Visa got first rejected and then approved [studntMst.VISA_APPROVED in ('N','Y')] and the file is processed [fileMst.FILE_PROCESSED = 'Y']

Following query is not returning any output.

SELECT 
studntMst.STUDENT_MST_ID,
studntMst.STUDENT_ID,
studntMst.VISA_APPROVED,
studntMst.UNIVERSITY_APPROVED,
fileMst.STUDENT_FILE_ID,
fileMst.FILE_PROCESSED
FROM 
STUDENT_MST studntMst
JOIN FILE_MST fileMst on fileMst.STUDENT_FILE_ID = studntMst.STUDENT_FILE_ID
and studntMst.VISA_APPROVED in ('N','Y')
and fileMst.FILE_PROCESSED = 'Y'
GROUP BY
studntMst.STUDENT_MST_ID,
studntMst.STUDENT_ID,
studntMst.VISA_APPROVED,
studntMst.UNIVERSITY_APPROVED,
fileMst.STUDENT_FILE_ID,
fileMst.FILE_PROCESSED
HAVING COUNT(studntMst.STUDENT_ID) > 1
ORDER BY studntMst.STUDENT_MST_ID desc;

Ideally it should return the following.

STUDENT_MST_ID STUDENT_ID VISA_APPROVED UNIVERSITY_APPROVED STUDENT_FILE_ID FILE_PROCESSED
9 STU-5 'Y' 'Y' FILE-8 'Y'
8 STU-5 'N' 'Y' FILE-7 'Y'
7 STU-5 'N' 'Y' FILE-6 'Y'
6 STU-4 'Y' 'Y' FILE-5 'Y'
5 STU-4 'N' 'Y' FILE-4 'Y'

Queries to create table and insert data.

CodePudding user response:

SELECT 
*
FROM 
STUDENT_MST studntMst
JOIN FILE_MST fileMst on fileMst.STUDENT_FILE_ID = studntMst.STUDENT_FILE_ID
and studntMst.STUDENT_ID in (
    SELECT 
    studntMst.STUDENT_ID
    FROM 
    STUDENT_MST studntMst
    JOIN FILE_MST fileMst on fileMst.STUDENT_FILE_ID = studntMst.STUDENT_FILE_ID
    and studntMst.VISA_APPROVED in ('N','Y')
    and fileMst.FILE_PROCESSED = 'Y'
    GROUP BY
    studntMst.STUDENT_ID
    HAVING COUNT(studntMst.STUDENT_ID) > 1
)
ORDER BY studntMst.STUDENT_MST_ID desc;

CodePudding user response:

You can follow up with three steps:

  • join the "STUDENT_MST" table with the "FILE_MST" table on matching "STUDENT_FILE_ID" field and filtering out non-processed files (f.FILE_PROCESSED <> 'Y')
  • use two SUM window functions, one to identify the amount of rejected visas, another to identify the amount of approved visas
  • filter out rows that have these window function values less than 1 (which means that the student has had their visa accepted and rejected at least once)
WITH cte AS (
    SELECT s.*, 
           SUM(CASE WHEN VISA_APPROVED = 'Y' THEN 1 END) OVER(PARTITION BY STUDENT_ID) AS y,
           SUM(CASE WHEN VISA_APPROVED = 'N' THEN 1 END) OVER(PARTITION BY STUDENT_ID) AS n
    FROM       STUDENT_MST s
    INNER JOIN FILE_MST    f
            ON s.STUDENT_FILE_ID = f.STUDENT_FILE_ID
           AND f.FILE_PROCESSED = 'Y'
)
SELECT STUDENT_MST_ID,
       STUDENT_ID,
       STUDENT_FILE_ID,
       VISA_APPROVED,
       UNIVERSITY_APPROVED
FROM cte
WHERE y >= 1 AND n >= 1

Check the demo here.

Assumption: rejected visas come always before accepted visas. If this is not the case, you need an additional LAST_VALUE window function which gathers the last value for the visa state, partitioned by each student. Eventually filter out those students whose last visa state is not 'Y'.

  • Related