Select id_student from each group id_student where id_desireCollage=5 not in first 5 rows student id.
| ID | id_desireCollage | id_student |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 4 | 1 |
| 6 | 5 | 1 |
| 7 | 2 | 2 |
| 8 | 5 | 2 |
| 9 | 1 | 2 |
| 10 | 3 | 2 |
| 11 | 7 | 2 |
| 12 | 4 | 3 |
| 13 | 3 | 3 |
| 14 | 2 | 3 |
| 15 | 1 | 3 |
| 16 | 8 | 3 |
| 17 | 9 | 3 |
| 18 | 7 | 3 |
| 19 | 5 | 3 |
I tried:
select id_student
from student_desire
group by(id_student)
having id_desireCollage not in first 5 rows
Expected result is:
| id_student |
|---|
| 3 |
CodePudding user response:
You can use ROW_NUMBER(). For example:
select id_student
from (
select t.*, row_number() over(partition by id_student order by id) as rn
from t
) x
where id_desireCollage = 5 and rn > 5
CodePudding user response:
Assuming the IDs are sequential within the group, you could query students where the difference between the ID of id_desireCollage=5 and the first id_desireCollage is more than 5:
SELECT id_student
FROM student_desire
GROUP BY id_student
HAVING MIN(CASE id_desireCollage WHEN 5 THEN id END) - MIN(id) > 5
CodePudding user response:
You can use the ROW_NUMBER analytic function:
SELECT id_student
FROM (
SELECT id_student,
id_desireCollage,
ROW_NUMBER() OVER (PARTITION BY id_student ORDER BY id) AS rn
FROM student_desire
)
WHERE id_desireCollage = 5
AND rn > 5;
or, from Oracle 12, (without any functions) using MATCH_RECOGNIZE:
SELECT id_student
FROM student_desire
MATCH_RECOGNIZE(
PARTITION BY id_student
ORDER BY id
PATTERN (^ not5{5,} id5)
DEFINE
not5 AS id_desireCollage != 5,
id5 AS id_desireCollage = 5
);
Which, for the sample data:
CREATE TABLE student_desire (ID, id_desireCollage, id_student) AS
SELECT 1, 1, 1 FROM DUAL UNION ALL
SELECT 2, 2, 1 FROM DUAL UNION ALL
SELECT 3, 3, 1 FROM DUAL UNION ALL
SELECT 4, 4, 1 FROM DUAL UNION ALL
SELECT 6, 5, 1 FROM DUAL UNION ALL
SELECT 7, 2, 2 FROM DUAL UNION ALL
SELECT 8, 5, 2 FROM DUAL UNION ALL
SELECT 9, 1, 2 FROM DUAL UNION ALL
SELECT 10, 3, 2 FROM DUAL UNION ALL
SELECT 11, 7, 2 FROM DUAL UNION ALL
SELECT 12, 4, 3 FROM DUAL UNION ALL
SELECT 13, 3, 3 FROM DUAL UNION ALL
SELECT 14, 2, 3 FROM DUAL UNION ALL
SELECT 15, 1, 3 FROM DUAL UNION ALL
SELECT 16, 8, 3 FROM DUAL UNION ALL
SELECT 17, 9, 3 FROM DUAL UNION ALL
SELECT 18, 7, 3 FROM DUAL UNION ALL
SELECT 19, 5, 3 FROM DUAL
All output:
| ID_STUDENT |
|---|
| 3 |
You can do it without analytic functions or MATCH_RECOGNIZE, using a correlated sub-query and aggregation functions instead, but its (much) less efficient (and does use the COUNT aggregation function):
SELECT id_student
FROM student_desire s
WHERE id <= ( SELECT id
FROM student_desire c
WHERE s.id_student = c.id_student
AND c.id_desireCollage = 5 )
GROUP BY id_student
HAVING COUNT(*) > 5
