SQL或PL / SQL查询打印给定N个数字的序列

时间:2014-07-23 13:13:14

标签: sql oracle plsql


我需要帮助构建查询,因为下面的structured.i尝试使用for循环,但它只是打印为1 2 3 4 5 6 7 8 9
例如,如果N值为9则表示输出应该是这样的。

示例输出

0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6
0 1 2 3 4 5
0 1 2 3 4
0 1 2 3
0 1 2
0 1
0

7 个答案:

答案 0 :(得分:2)

要在SQL中执行此操作 - 如果您希望能够指定n,则需要使用绑定变量 - 您需要将start与connect by组合并从那里构建。这是一种方式,但我非常确定可以在没有union的情况下完成:

with t as (
  select level as rn, level - 1 as val
  from dual
  connect by level <= :n + 1
)
select t1.rn as rn,
  listagg(t2.val, ' ') within group (order by t2.val) as answer
from t t1
join t t2 on t2.val <= t1.val
group by t1.rn, t1.val
union all
select (2 * (:n + 1)) - t1.rn,
  listagg(t2.val, ' ') within group (order by t2.val) as answer
from t t1
join t t2 on t2.val <= t1.val
where t1.rn <= :n
group by t1.rn, t1.val
order by rn;

CTE生成数字0到n。联合的两半创造了输出的镜像半部;第二个有rn <= :n过滤器,以防止“中间”过滤线被重复。

使用:

var n number;
exec :n := 9;

这给出了:

    RN ANSWER                                 
------ ----------------------------------------
     1 0                                        
     2 0 1                                      
     3 0 1 2                                    
     4 0 1 2 3                                  
     5 0 1 2 3 4                                
     6 0 1 2 3 4 5                              
     7 0 1 2 3 4 5 6                            
     8 0 1 2 3 4 5 6 7                          
     9 0 1 2 3 4 5 6 7 8                        
    10 0 1 2 3 4 5 6 7 8 9                      
    11 0 1 2 3 4 5 6 7 8                        
    12 0 1 2 3 4 5 6 7                          
    13 0 1 2 3 4 5 6                            
    14 0 1 2 3 4 5                              
    15 0 1 2 3 4                                
    16 0 1 2 3                                  
    17 0 1 2                                    
    18 0 1                                      
    19 0                                        

或6:

exec:n:= 6;

    RN ANSWER                                 
------ ----------------------------------------
     1 0                                        
     2 0 1                                      
     3 0 1 2                                    
     4 0 1 2 3                                  
     5 0 1 2 3 4                                
     6 0 1 2 3 4 5                              
     7 0 1 2 3 4 5 6                            
     8 0 1 2 3 4 5                              
     9 0 1 2 3 4                                
    10 0 1 2 3                                  
    11 0 1 2                                    
    12 0 1                                      
    13 0    

你真的不想看到rn,但你可以通过将它放在子查询中来删除它。

答案 1 :(得分:1)

使用while循环:

DECLARE
  my_limit SIMPLE_INTEGER := 9;
  my_step  SIMPLE_INTEGER := +1;
  i SIMPLE_INTEGER := 0;
  s VARCHAR2(32000);
BEGIN
  WHILE (i > -1) LOOP
    s := '';
    FOR j IN 0 .. i LOOP
      IF j>0 THEN s := s || ' '; END IF;
      s := s || to_char(j);
    END LOOP;
    dbms_output.put_line(s);

    IF (i >= my_limit) THEN my_step := -1; END IF;
    i := i + my_step;
  END LOOP;
END;
/

答案 2 :(得分:1)

我认为, sys_connect_by_path 正是您所寻找的。

Oracle Doc

SYS_CONNECT_BY_PATH仅在分层查询中有效。它返回从根到节点的列值的路径,对于CONNECT BY条件返回的每一行,列值由char分隔。

with desired_number as (select 5 as nm from dual)
,tree
 as (    select level - 1 as a, sys_connect_by_path(level - 1, ' ') as b, nm
           from dual, desired_number
     connect by level <= nm + 1)
select *
from (select a, b from tree
      union all
      select 2 * nm - a, b
        from tree
       where a != nm)
order by a
不过,你怎么像sql那样格式化它?

答案 3 :(得分:1)

此选择查询可提供准确的结果:

WITH CTE1 AS 
(SELECT 9 AS COL FROM DUAL)
,CTE2
AS (    
SELECT LEVEL - 1 AS A,
SYS_CONNECT_BY_PATH(LEVEL - 1, ' ') AS B,
COL
FROM DUAL, CTE1
CONNECT BY LEVEL <= COL + 1)
SELECT B
FROM (SELECT A, B FROM CTE2
UNION ALL
SELECT 2 * COL - A, B
FROM CTE2
WHERE A != COL)
ORDER BY A;

<强>输出:

 0
 0 1
 0 1 2
 0 1 2 3
 0 1 2 3 4
 0 1 2 3 4 5
 0 1 2 3 4 5 6
 0 1 2 3 4 5 6 7
 0 1 2 3 4 5 6 7 8
 0 1 2 3 4 5 6 7 8 9
 0 1 2 3 4 5 6 7 8
 0 1 2 3 4 5 6 7
 0 1 2 3 4 5 6
 0 1 2 3 4 5
 0 1 2 3 4
 0 1 2 3
 0 1 2
 0 1
 0

答案 4 :(得分:0)

您可能会发现通过建立连接,以便找到答案。

select level n
from dual
connect by level <= 10

答案 5 :(得分:0)

使用三个嵌套for循环:

DECLARE
  my_limit SIMPLE_INTEGER := 9;

  PROCEDURE one_line(n simple_integer) IS
    s VARCHAR2(4000);
  BEGIN
    FOR j IN 0 .. n LOOP
      IF j>0 THEN s := s || ' '; END IF;    
      s := s || to_char(j);
    END LOOP;
    dbms_output.put_line(s);
  END one_line;
BEGIN
  FOR i IN 0 .. my_limit LOOP
    one_line(i);
  END LOOP;
  FOR i IN REVERSE 0 .. my_limit-1 LOOP
    one_line(i);
  END LOOP;  
END;
/

答案 6 :(得分:0)

终于明白了:

  WITH CTE AS
  (
        SELECT LEVEL-1 COL
        FROM DUAL
        CONNECT BY LEVEL <= 10
  )

  SELECT SYS_CONNECT_BY_PATH(COL, ' ') COL  
  FROM ( SELECT COL,
         ROW_NUMBER() OVER (ORDER BY COL) RN
         FROM CTE) 
      START WITH RN = 1 
      CONNECT BY PRIOR RN = RN - 1 
  UNION ALL

  SELECT COL FROM( 
      SELECT  RPAD(SYS_CONNECT_BY_PATH(COL, ' ') , '20'  )COL 
      FROM ( SELECT COL,
              ROW_NUMBER() OVER (ORDER BY COL) RN
              FROM CTE)
      START WITH RN = 1 
      CONNECT BY PRIOR RN = (RN - 1 )
      ORDER BY COL DESC
  );

生成此输出:

0
 0 1
 0 1 2
 0 1 2 3
 0 1 2 3 4
 0 1 2 3 4 5
 0 1 2 3 4 5 6
 0 1 2 3 4 5 6 7
 0 1 2 3 4 5 6 7 8
 0 1 2 3 4 5 6 7 8 9
 0 1 2 3 4 5 6 7 8 9
 0 1 2 3 4 5 6 7 8  
 0 1 2 3 4 5 6 7    
 0 1 2 3 4 5 6      
 0 1 2 3 4 5        
 0 1 2 3 4          
 0 1 2 3            
 0 1 2              
 0 1                
 0