Little explanation:
I have a table called passes
and it's linked with 2 tables ( services
(cod_serv) and atend
(pass)). Passes can be duplicated for different services.
Eg.: If I have 3 services, I can have 3 passes nº 01, BUT not 2 passes nº 1 for the same service (I defined it in my composite primary key).
For tests, I added 102 passes (all with situation = "F" and with the same date (today)). Then I added 34 passes for each service (I have 3 services).
The following query is to show how the schema
more or less defined.
SELECT DISTINCT s.pass, s.data, cod_serv, situation, hour, min
FROM passes
JOIN atend a ON s.pass = a.pass;
PASS DATA COD_SERV S HOUR MIN
----- -------- --------- - ------- -------
04 26/03/16 2 F 12 24
04 26/03/16 1 F 13 27
13 26/03/16 1 F 14 26
18 26/03/16 3 F 14 27
18 26/03/16 2 F 14 28
15 26/03/16 1 F 14 29
10 26/03/16 3 F 14 30
... ... ... ... ... ...
Then, I want to get the 100th ( ROWNUMBER()
) pass (as it's showing below it's 21) from a specific date with the situation = 'F' ordering by hour and min.
Row Number 100:
21 26/03/16 3 F 14 34
The following query
is returning nothing and I can't figure out why. By the way, I have more than 100 passes with this situation.
SELECT DISTINCT pass, data, cod_serv, situation FROM
(SELECT DISTINCT a.pass, s.data, cod_serv, situation,
ROW_NUMBER() OVER(PARTITION BY situation, hour, min
ORDER BY situation, hour, min) row
FROM passes s
JOIN atend a ON s.pass = a.pass
WHERE situation = 'F' AND
TRUNC(a.data) = TRUNC('some date'))
WHERE row = 100;
EDIT:
My query at the moment:
SELECT DISTINCT pass, cod_serv FROM
(SELECT DISTINCT s.pass, cod_serv,
ROW_NUMBER() OVER(PARTITION BY TRUNC(s.data)
ORDER BY a.hour, a.min) row
FROM passes s
JOIN atend a ON s.pass = a.pass
WHERE s.situation = 'F' AND
TRUNC(s.data) = TRUNC(SYSDATE))
WHERE row = 100;
Having the same fields in PARTITION BY
and ORDER BY
in an OVER
clause makes little sense.
The PARTITION BY
clause should list the fields that define the group in which you start counting records from 1.
The ORDER BY
clause defines the order in which records are counted within that group.
As you write:
I want to get the 100th (
ROWNUMBER()
) pass from a specific date with the situation = 'F' ordering by hour and min
... you actually say in words what needs to be put in these clauses:
ROW_NUMBER() OVER(PARTITION BY data, situation ORDER BY hour, min)
So your main mistake was to put hour and min in the PARTITION BY
clause, making the record count starting from 1 as soon as a minute difference was found, giving most of your records the number 1.
Edit
It seems that Oracle does not retain the same row
number when it is not selected. This is probably because the ORDER BY hour, min
is not deterministic. Whatever the reason, it can be solved by selecting the row
in the outer query:
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
If you only need the pass, you can wrap that query again:
SELECT pass FROM (
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
)
How about this?
First, before doing row_number()
, apply ALL of your filters (since you don't want to count the rows that you're going to filter out):
SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min
FROM passes s
JOIN atend a ON s.pass = a.pass
WHERE s.situation = 'F'
AND TRUNC(s.data) = TRUNC(SYSDATE)
Now, wrap that in an outer query where you apply row_number()
:
SELECT pass, data, cod_serv, situation, hour, min,
rowseq=row_number() over (order by hour, min)
FROM (
SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min
FROM passes s
JOIN atend a ON s.pass = a.pass
WHERE s.situation = 'F'
AND TRUNC(s.data) = TRUNC(SYSDATE)
) t1
Finally, wrap that in an outer query where you apply the filter for the "hundredth" record:
SELECT pass, data, cod_serv, situation, hour, min
FROM (
SELECT pass, data, cod_serv, situation, hour, min,
rowseq=row_number() over (order by hour, min)
FROM (
SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min
FROM passes s
JOIN atend a ON s.pass = a.pass
WHERE s.situation = 'F'
AND TRUNC(s.data) = TRUNC(SYSDATE)
) t1
WHERE rowseq = 100
Lastly, if any parts need adjusting (different filters, joins, etc.), you can run each of these levels of inner queries on their own to check your intermediate results to make sure your final result is what you want.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.