Oracle 11g:如何在SQL查询中选择“额外”行

时间:2016-06-04 16:51:25

标签: sql oracle

使用Oracle 11g,并在工程文档上下文中工作,我需要选择一组行,这些行包含先前转速和多个文档表的“额外”行。

具体来说,我们的数据库只记录了每个工程文档的最新版本。我们需要为每个修订版和这些记录的每一页返回一行。

我们有这样的数据:

DRAW_NUM        REV NUM_SHTS
LD-111-639-01   2   3

我们需要这样的数据:

DRAW_NUM        REV SHT
LD-111-639-01   1   1
LD-111-639-01   1   2
LD-111-639-01   1   3
LD-111-639-01   2   1
LD-111-639-01   2   2
LD-111-639-01   2   3

我最近的SQLPlus查询尝试使用外部表列出从0到Rev和0到Num_Shts的数字,代码如下所示:

SELECT DISTINCT prefix || '-' || lpad(series,3,0) || '-' || lpad(base,3,0) || '-' || lpad(suffix,2,0) Draw_Num,
(select n from numbers where n >=0 and n <= md_draw.rev) Rv,
(select n from numbers where n >=0 and n <= md_draw.num_shts) Sht
FROM md_draw WHERE Dwg_Date <= TO_DATE('1-JUN-02')
ORDER BY Draw_Num, Rv, Sht
/

但产生以下错误:

  

ORA-01427:单行子查询返回多行

有一种简单的方法吗?

3 个答案:

答案 0 :(得分:1)

您的两个子查询返回多行,您需要使用某种聚合函数(Min()Max()等)指定所需的单个项目:

SELECT DISTINCT prefix || '-' || lpad(series,3,0) || '-' || lpad(base,3,0) || '-' || lpad(suffix,2,0) Draw_Num,
(select Max(n) from numbers where n >=0 and n <= md_draw.rev) Rv,
(select Max(n) from numbers where n >=0 and n <= md_draw.num_shts) Sht
FROM md_draw WHERE Dwg_Date <= TO_DATE('1-JUN-02')
ORDER BY Draw_Num, Rv, Sht

或者,如果您需要所有这些,则应使用JOIN而不是子查询:

SELECT DISTINCT prefix || '-' || lpad(series,3,0) || '-' || lpad(base,3,0) || '-' || lpad(suffix,2,0) Draw_Num, 
       n1.n As Rv, n2.n As Shts
FROM md_draw 
JOIN numbers n1 
ON n1.n BETWEEN 0 AND md_draw.rev
JOIN numbers n2
ON n2.n BETWEEN 0 AND md_draw.num_shts
WHERE Dwg_Date <= TO_DATE('1-JUN-02')
ORDER BY Draw_Num, Rv, Sht

您可能需要调整最后一个查询,我没有时间通过​​sqlfiddle或其他任何方式运行它,但它应该让您基本了解该怎么做。只是一个观察,我不知道revnum_shtsn表中的numbers有什么关系。

答案 1 :(得分:0)

这是因为下面的子查询产生了超过1行。如果md_drawnumbers之间存在关联,请考虑执行JOIN

(select n from numbers where n >=0 and n <= md_draw.rev) Rv

答案 2 :(得分:0)

Oracle安装程序

CREATE TABLE table_name ( DRAW_NUM, REV, NUM_SHTS ) AS
SELECT 'LD-111-639-01', 2, 3 FROM DUAL UNION ALL
SELECT 'LD-111-639-02', 0, 2 FROM DUAL UNION ALL
SELECT 'LD-111-639-03', 7, 0 FROM DUAL UNION ALL
SELECT 'LD-111-639-04', 1, 2 FROM DUAL;

查询 - 使用递归子查询分解子句

WITH rsqfc ( draw_num, rev, num_shts, rv, sht ) AS (
  SELECT draw_num, rev, num_shts, 1, 1
  FROM   table_name
  WHERE  REV > 0 AND num_shts > 0
UNION ALL
  SELECT draw_num, rev, num_shts,
         CASE sht WHEN num_shts THEN rv+1 ELSE rv END,
         CASE sht WHEN num_shts THEN 1 ELSE sht+1 END
  FROM   rsqfc
  WHERE  rv < rev
  OR     sht < num_shts
)
SELECT draw_num, rv AS rev, sht
FROM   rsqfc
ORDER BY draw_num, rv, sht;

查询 - 使用分层查询

SELECT t.draw_num,
       r.COLUMN_VALUE AS rev,
       n.COLUMN_VALUE AS sht
FROM   table_name t,
       TABLE(
         CAST(
           MULTISET(
             SELECT LEVEL
             FROM   DUAL
             WHERE  t.REV > 0
             CONNECT BY LEVEL <= t.REV
           ) AS SYS.ODCINUMBERLIST
         )
       ) r,
       TABLE(
         CAST(
           MULTISET(
             SELECT LEVEL
             FROM   DUAL
             WHERE  t.NUM_SHTS > 0
             CONNECT BY LEVEL <= t.NUM_SHTS
           ) AS SYS.ODCINUMBERLIST
         )
       ) n;

<强>输出

DRAW_NUM             REV        SHT
------------- ---------- ----------
LD-111-639-01          1          1 
LD-111-639-01          1          2 
LD-111-639-01          1          3 
LD-111-639-01          2          1 
LD-111-639-01          2          2 
LD-111-639-01          2          3 
LD-111-639-04          1          1 
LD-111-639-04          1          2 
相关问题