[英]Oracle 11g: How To Select 'Extra' Rows in SQL Query
使用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:單行子查詢返回多個行
是否有捷徑可尋?
您的兩個子查詢將返回多行,您將需要使用某種聚合函數( 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
與您的numbers
表中的n
有什么關系。
那是因為下面的子查詢產生了多於1行。 如果md_draw
和numbers
之間存在關系,則考慮進行JOIN
(select n from numbers where n >=0 and n <= md_draw.rev) Rv
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.