Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 使用单个select语句从表中获取下一行,如果到达表的末尾,则返回第一行_Oracle_Plsql - Fatal编程技术网

Oracle 使用单个select语句从表中获取下一行,如果到达表的末尾,则返回第一行

Oracle 使用单个select语句从表中获取下一行,如果到达表的末尾,则返回第一行,oracle,plsql,Oracle,Plsql,我有一张桌子,上面写着如下工作人员: STAFF_NAME ============ ALEX BERNARD CARL DOMINIC EMMA 现在,我想用一个参数编写一个存储函数。例如,获取下一个员工(当前员工)。 输入和输出应如下所示: Input | Output ===================== NULL | ALEX ALEX | BERNARD BERNARD | CARL EMMA | ALEX (Start from the beginn

我有一张桌子,上面写着如下工作人员:

STAFF_NAME
============
ALEX
BERNARD
CARL
DOMINIC
EMMA
现在,我想用一个参数编写一个存储函数。例如,
获取下一个员工(当前员工)。

输入和输出应如下所示:

Input   |   Output
=====================
NULL    | ALEX
ALEX    | BERNARD
BERNARD | CARL
EMMA    | ALEX (Start from the beginning of the table again)

我知道如何使用PL/SQL处理此问题,但是否可以使用单个select语句来处理此问题?

在下面的解决方案中,我假设行按名称的字母顺序排列。它们可以按同一表中的另一列排序(例如,按雇用日期、或按工资等排序,这无关紧要),然后在两个分析函数的ORDER by子句中应使用该列的名称

输入名称作为绑定变量传入,
:input\u staff\u name
。该解决方案使用纯SQL,不需要函数(PL/SQL),但如果必须将其转换为函数,则可以轻松地进行调整

编辑:在我的原始答案中,当输入为
null
时,我错过了所需的行为。最后一行代码(不包括分号)处理这个问题。如当前编写的,当输入为
null
时,查询返回ALEX(或通常是表中的第一个值),当输入不为null且不在表中时,查询不返回任何行。相反,如果要求在输入为
null
或未在表中找到时返回第一个名称,则可以通过从最后一行中删除
和:input\u staff\u name为null
来轻松调整

with
     tbl ( staff_name ) as (
       select 'ALEX'    from dual union all
       select 'BERNARD' from dual union all
       select 'CARL'    from dual union all
       select 'DOMINIC' from dual union all
       select 'EMMA'    from dual
     ),
     prep ( staff_name, next_name, first_name ) as (
       select staff_name, 
              lead(staff_name)         over (order by staff_name),
              first_value (staff_name) over (order by staff_name)
       from   tbl
     )
select nvl(next_name, first_name) as next_staff_name
from   prep
where  staff_name = :input_staff_name 
   or  (next_name is null and :input_staff_name is null)
;

在下面的解决方案中,我假设行是按名称的字母顺序排列的。它们可以按同一表中的另一列排序(例如,按雇用日期、或按工资等排序,这无关紧要),然后在两个分析函数的ORDER by子句中应使用该列的名称

输入名称作为绑定变量传入,
:input\u staff\u name
。该解决方案使用纯SQL,不需要函数(PL/SQL),但如果必须将其转换为函数,则可以轻松地进行调整

编辑:在我的原始答案中,当输入为
null
时,我错过了所需的行为。最后一行代码(不包括分号)处理这个问题。如当前编写的,当输入为
null
时,查询返回ALEX(或通常是表中的第一个值),当输入不为null且不在表中时,查询不返回任何行。相反,如果要求在输入为
null
或未在表中找到时返回第一个名称,则可以通过从最后一行中删除
和:input\u staff\u name为null
来轻松调整

with
     tbl ( staff_name ) as (
       select 'ALEX'    from dual union all
       select 'BERNARD' from dual union all
       select 'CARL'    from dual union all
       select 'DOMINIC' from dual union all
       select 'EMMA'    from dual
     ),
     prep ( staff_name, next_name, first_name ) as (
       select staff_name, 
              lead(staff_name)         over (order by staff_name),
              first_value (staff_name) over (order by staff_name)
       from   tbl
     )
select nvl(next_name, first_name) as next_staff_name
from   prep
where  staff_name = :input_staff_name 
   or  (next_name is null and :input_staff_name is null)
;

根据@mathguy的回答,我做了一些似乎有效的修改。我添加了以下内容

UNION ALL
 SELECT NULL
   FROM DUAL

其中NVL(职员姓名,'X')=NVL(NULL,'X')

完整代码

WITH tbl (staff_name) AS
    (SELECT 'ALEX' FROM DUAL
     UNION ALL
     SELECT 'BERNARD' FROM DUAL
     UNION ALL
     SELECT 'CARL' FROM DUAL
     UNION ALL
     SELECT 'DOMINIC' FROM DUAL
     UNION ALL
     SELECT 'EMMA' FROM DUAL
     UNION ALL
     SELECT NULL
       FROM DUAL),
 prep (staff_name,
       next_name,
       first_name,
       last_name) AS
    (SELECT staff_name,
            LEAD (staff_name) OVER (ORDER BY staff_name),
            FIRST_VALUE (staff_name) OVER (ORDER BY staff_name),
            LAG (staff_name) OVER (ORDER BY staff_name)
       FROM tbl) 
SELECT NVL (next_name, first_name) AS next_staff_name
  FROM prep
 WHERE NVL (staff_name, 'X') = NVL (:input_staff_name, 'X');

根据@mathguy的回答,我做了一些似乎有效的修改。我添加了以下内容

UNION ALL
 SELECT NULL
   FROM DUAL

其中NVL(职员姓名,'X')=NVL(NULL,'X')

完整代码

WITH tbl (staff_name) AS
    (SELECT 'ALEX' FROM DUAL
     UNION ALL
     SELECT 'BERNARD' FROM DUAL
     UNION ALL
     SELECT 'CARL' FROM DUAL
     UNION ALL
     SELECT 'DOMINIC' FROM DUAL
     UNION ALL
     SELECT 'EMMA' FROM DUAL
     UNION ALL
     SELECT NULL
       FROM DUAL),
 prep (staff_name,
       next_name,
       first_name,
       last_name) AS
    (SELECT staff_name,
            LEAD (staff_name) OVER (ORDER BY staff_name),
            FIRST_VALUE (staff_name) OVER (ORDER BY staff_name),
            LAG (staff_name) OVER (ORDER BY staff_name)
       FROM tbl) 
SELECT NVL (next_name, first_name) AS next_staff_name
  FROM prep
 WHERE NVL (staff_name, 'X') = NVL (:input_staff_name, 'X');

您是否认为员工姓名也对订单进行编码?(可能按字母顺序排列?)或者您是否考虑了其他顺序,可能编码在不同的列中?(或者你认为表中的顺序是自然排序的吗?你知道这不是真的,对吧?表中没有“自然”的行顺序。)记录可能不会排序,但如果有必要,我可以这样做。??如果记录没有分类,“下一个”员工是什么意思?“下一步”是一个基于订单的概念。您是否认为员工姓名也对订单进行编码?(可能按字母顺序排列?)或者您是否考虑了其他顺序,可能编码在不同的列中?(或者你认为表中的顺序是自然排序的吗?你知道这不是真的,对吧?表中没有“自然”的行顺序。)记录可能不会排序,但如果有必要,我可以这样做。??如果记录没有分类,“下一个”员工是什么意思?“下一步”是一个基于订单的概念。由于
:input\u staff\u name
可以为空,您能帮助改进您的答案吗?对不起,我在“output table”中遗漏了这一点。我在末尾添加了一行代码,它将处理
NULL
输入。注意:在最后一行代码中,您可以删除“and:input\u staff\u name is null”-并保留“or next\u name is null”。在这种情况下,每当输入为null或表中未找到任何字符串时,输出将为ALEX。正如
:input\u staff\u name
可以为null,您能帮助改进您的答案吗?抱歉,我在“输出表”。我在末尾添加了一行代码,用于处理
NULL
输入。注意:在最后一行代码中,您可以删除“and:input\u staff\u name is NULL”-并保留“或next\u name is NULL”“在这种情况下,每当输入为NULL或表中未找到任何字符串时,输出将为ALEX。您可以猜测,如果输入为NULL,则结果应为ALEX。这不是一个明显的选择。在这种情况下,我只是要求OP澄清(以及当输入为ROSE时,例如-在表中找不到名称)。OP在他的示例中说明,当输入为
NULL
时,输出应为
ALEX
,因此是的,我假设当输入为
NULL
否时,它应返回第一个名称,OP没有这么说。OP表示当到达末尾时,应返回第一行。在本例中,如果输入为EMMA,则结果应为ALEX。(在示例表中显示得非常清楚!)没有提到当-INPUT-为NULL时该怎么做(不是结果!)在示例表中显示,INPUT NULL应该给出输出ALEX。这是桌子的第一排。哦。。。你说得对,我错过了。我必须检查一下我的眼睛,我看了那张桌子好几次,还是没看到。我现在看到了!你猜对了