繁体   English   中英

Oracle中的ROWNUMBER函数

[英]ROWNUMBER function in Oracle

小解释:

我有一个名为passes的表,它与2个表( 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;

OVER子句的PARTITION BYORDER BY中具有相同的字段几乎没有意义。

PARTITION BY子句应列出定义从1开始对记录进行计数的组的字段。

ORDER BY子句定义该组中记录的计数顺序。

在您撰写时:

我想从特定日期获得第100次( ROWNUMBER() )传递,情况='F',按小时和分钟排序

...您实际上是在说这些条款中需要写的内容:

 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

最后,将其包装在外部查询中,在其中将过滤器应用于“一百”条记录:

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

最后,如果任何部分需要调整(不同的过滤器,联接等),则可以自行运行这些内部查询级别中的每一个,以检查中间结果,以确保最终结果是所需的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM