Using Oracle 11g, and working in an engineering document context, I need to select a collection of rows that include 'extra' rows for prior revs and multiple document sheets.
Specifically, our database has a record for only the latest revision of each engineering document. We need a row returned for each revision and each sheet of these records.
We have data like this:
DRAW_NUM REV NUM_SHTS
LD-111-639-01 2 3
We Need Data Like This:
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
My latest SQLPlus query attempt uses an external table to list numbers from 0 to Rev and 0 to Num_Shts, and the code looks like this:
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
/
But produces the following error:
ORA-01427: single-row subquery returns more than one row
Is there an easy way to do this?
Your two sub-queries are returning multiple rows, you will need to specify which single item you want with either an aggregate function of some kind ( Min()
, Max()
, etc...):
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
Or, if you need all of them, you should use JOIN
s instead of sub-queries:
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
You may need to tweak that last query, I didn't have time to run it through sqlfiddle or anything, but it should give you a basic idea of what to do. Just an observation, I don't see what relation both rev
and num_shts
has to do with n
in your numbers
table.
That's because of the subquery below which is producing more than 1 row. If there is a relation between md_draw
and numbers
then consider doing a JOIN
(select n from numbers where n >=0 and n <= md_draw.rev) Rv
Oracle Setup :
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;
Query - Using a recursive sub-query factoring clause :
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;
Query - Using Hierarchical Queries :
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;
Output :
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.