Oracle 中的 ROWNUMBER 函数
ROWNUMBER function in Oracle
小说明:
我有一个名为 passes
的 table,它与 2 tables (services
(cod_serv) 和 atend
(经过))。可以为不同的服务复制通行证。
例如:如果我有 3 项服务,我可以有 3 次 nº 01 传递,但是 不是 2 次传递 nº 1 用于相同的服务(我在我的复合主项中定义了它键)。
对于测试,我添加了 102 次通过(所有情况都为 "F" 且日期相同(今天))。然后我为每项服务添加了 34 通行证(我有 3 项服务)。
下面的查询是为了显示 schema
或多或少是如何定义的。
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
... ... ... ... ... ...
然后,我想从特定日期获得第 100 (ROWNUMBER()
) 次通过(如下所示为 21),情况 = 'F' 按小时和分钟排序。
第 100 行:
21 26/03/16 3 F 14 34
以下 query
没有返回任何内容,我不明白为什么。顺便说一句,我有超过100次通过这种情况。
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;
编辑:
我现在的查询:
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;
在 PARTITION BY
和 ORDER BY
中的 OVER
子句中具有相同的字段毫无意义。
PARTITION BY
子句应列出定义您从 1 开始计算记录的组的字段。
ORDER BY
子句定义记录在该组中的计数顺序。
如您所写:
I want to get the 100th (ROWNUMBER()
) pass from a specific date with the situation = 'F' ordering by hour and min
...你实际上用文字说出这些条款中需要放入的内容:
ROW_NUMBER() OVER(PARTITION BY data, situation ORDER BY hour, min)
所以你的主要错误是把小时和分钟放在PARTITION BY
子句中,使记录计数从一旦发现一分钟的差异,立即为 1,为您的大部分记录分配数字 1。
编辑
好像Oracle在没有选择的时候没有保留相同的row
号。这可能是因为 ORDER BY hour, min
不是确定性的。无论是什么原因,都可以通过在外部查询中选择row
来解决:
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
如果您只需要通行证,您可以再次包装该查询:
SELECT pass FROM (
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
)
这个怎么样?
首先,在执行 row_number()
之前,应用所有过滤器(因为您不想计算要过滤掉的行数):
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)
现在,将其包装在您应用 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
最后,将其包装在外部查询中,在该查询中为 "hundredth" 记录应用过滤器:
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
最后,如果任何部分需要调整(不同的过滤器、连接等),您可以 运行 这些级别的内部查询中的每一个都自己检查您的中间结果,以确保您的 最终结果如你所愿
小说明:
我有一个名为 passes
的 table,它与 2 tables (services
(cod_serv) 和 atend
(经过))。可以为不同的服务复制通行证。
例如:如果我有 3 项服务,我可以有 3 次 nº 01 传递,但是 不是 2 次传递 nº 1 用于相同的服务(我在我的复合主项中定义了它键)。
对于测试,我添加了 102 次通过(所有情况都为 "F" 且日期相同(今天))。然后我为每项服务添加了 34 通行证(我有 3 项服务)。
下面的查询是为了显示 schema
或多或少是如何定义的。
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
... ... ... ... ... ...
然后,我想从特定日期获得第 100 (ROWNUMBER()
) 次通过(如下所示为 21),情况 = 'F' 按小时和分钟排序。
第 100 行:
21 26/03/16 3 F 14 34
以下 query
没有返回任何内容,我不明白为什么。顺便说一句,我有超过100次通过这种情况。
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;
编辑:
我现在的查询:
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;
在 PARTITION BY
和 ORDER BY
中的 OVER
子句中具有相同的字段毫无意义。
PARTITION BY
子句应列出定义您从 1 开始计算记录的组的字段。
ORDER BY
子句定义记录在该组中的计数顺序。
如您所写:
I want to get the 100th (
ROWNUMBER()
) pass from a specific date with the situation = 'F' ordering by hour and min
...你实际上用文字说出这些条款中需要放入的内容:
ROW_NUMBER() OVER(PARTITION BY data, situation ORDER BY hour, min)
所以你的主要错误是把小时和分钟放在PARTITION BY
子句中,使记录计数从一旦发现一分钟的差异,立即为 1,为您的大部分记录分配数字 1。
编辑
好像Oracle在没有选择的时候没有保留相同的row
号。这可能是因为 ORDER BY hour, min
不是确定性的。无论是什么原因,都可以通过在外部查询中选择row
来解决:
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
如果您只需要通行证,您可以再次包装该查询:
SELECT pass FROM (
SELECT pass, row FROM ( ... etc ...) WHERE row = 100
)
这个怎么样?
首先,在执行 row_number()
之前,应用所有过滤器(因为您不想计算要过滤掉的行数):
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)
现在,将其包装在您应用 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
最后,将其包装在外部查询中,在该查询中为 "hundredth" 记录应用过滤器:
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
最后,如果任何部分需要调整(不同的过滤器、连接等),您可以 运行 这些级别的内部查询中的每一个都自己检查您的中间结果,以确保您的 最终结果如你所愿