使用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:单行子查询返回多行
有一种简单的方法吗?
答案 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或其他任何方式运行它,但它应该让您基本了解该怎么做。只是一个观察,我不知道rev
和num_shts
与n
表中的numbers
有什么关系。
答案 1 :(得分:0)
这是因为下面的子查询产生了超过1行。如果md_draw
和numbers
之间存在关联,请考虑执行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