我遇到这样的情况,我需要根据共同的键属性为每一行分别找到分钟,第二分钟,第三分钟等等。
表1(数量> = 1)
╔═══════════════════╗
║ Item Location Qty ║
╠═══════════════════╣
║ 500 Loc1 5 ║
║ 501 Loc2 2 ║
║ 501 Loc3 1 ║
╚═══════════════════╝
表2(始终为1)
╔══════════════════════════╗
║ Item Location Qty Asset ║
╠══════════════════════════╣
║ 500 Loc1 1 11 ║
║ 500 Loc1 1 12 ║
║ 500 Loc1 1 13 ║
║ 500 Loc1 1 14 ║
║ 500 Loc1 1 15 ║
║ 500 Loc1 1 10 ║
║ 500 Loc1 1 9 ║
║ 500 Loc1 1 8 ║
║ 500 Loc1 1 7 ║
║ 501 Loc2 1 27 ║
╚══════════════════════════╝
必需的输出-如果表1中的数量为5,则输出应具有5行(即使表2中少于5行)
并且每行应具有min,2nd min,3rd min,4th min和第5分钟资产。
示例输出:
╔══════════════════════════╗
║ Item Location Qty Asset ║
╠══════════════════════════╣
║ 500 Loc1 1 7 ║
║ 500 Loc1 1 8 ║
║ 500 Loc1 1 9 ║
║ 500 Loc1 1 10 ║
║ 500 Loc1 1 11 ║
║ 501 Loc2 1 27 ║
║ 501 Loc2 1 ║
║ 501 Loc3 1 ║
╚══════════════════════════╝
答案 0 :(得分:2)
您可以使用分层查询根据table1
将qty
行转换为多行:
select item, location, qty, level as rn
from table1
connect by level <= qty
and item = prior item
and location = prior location
and prior dbms_random.value is not null;
我包含了level as rn
,以后可以用作伪密钥。
您可以使用解析函数从table2
行中获得等效的键值;我假设您是指分钟,第二分钟等。是指资产应显示的顺序,因此该列用于order by
子句:
select t2.*,
row_number() over (partition by item, location order by asset) as rn
from table2 t2;
然后,如果您同时提供CTE和CTE,则可以外部加入结果:
with t1 as (
select item, location, qty, level as rn
from table1
connect by level <= qty
and item = prior item
and location = prior location
and prior dbms_random.value is not null
),
t2 as (
select t2.*,
row_number() over (partition by item, location order by asset) as rn
from table2 t2
)
select t1.item, t1.location, 1 as qty, t2.asset
from t1
left join t2 on t2.item = t1.item and t2.location = t1.location and t2.rn = t1.rn;
使用项目,位置和上面两个子查询中的伪rn
值作为合并的跟踪条件。
您的样本数据将得到:
ITEM LOCATION QTY ASSET
---------- -------- ---------- ----------
500 Loc1 1 7
500 Loc1 1 8
500 Loc1 1 9
500 Loc1 1 10
500 Loc1 1 11
501 Loc2 1 27
501 Loc2 1
501 Loc3 1
8 rows selected.
答案 1 :(得分:1)
一种略短的方法:
select il.item, il.loc, il.qty, a.asset
from item_locations il
cross apply ( SELECT rownum rn FROM dual CONNECT BY level <= il.qty ) rn
left outer join lateral
( SELECT row_Number() over ( order by a.asset) rn, a.asset
FROM assets a
WHERE a.item = il.item and a.loc = il.loc) a ON a.rn = rn.rn;
基本上,rn
联接为每个qty
值生成一行,然后根据资产编号的排序位置对资产进行外部联接。
带有数据的完整示例:
with item_locations ( item, loc, qty ) AS
( SELECT 500, 'Loc1', 5 FROM DUAL UNION ALL
SELECT 501, 'Loc2', 2 FROM DUAL UNION ALL
SELECT 501, 'Loc3', 1 FROM DUAL ),
assets ( item, loc, qty, asset ) AS (
SELECT 500, 'Loc1', 1, 11 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 12 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 13 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 14 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 15 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 10 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 9 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 8 FROM DUAL UNION ALL
SELECT 500, 'Loc1', 1, 7 FROM DUAL UNION ALL
SELECT 501, 'Loc2', 1, 27 FROM DUAL )
select il.item, il.loc, il.qty, a.asset
from item_locations il
cross apply ( SELECT rownum rn FROM dual CONNECT BY level <= il.qty ) rn
left outer join lateral
( SELECT row_Number() over ( order by a.asset) rn, a.asset
FROM assets a
WHERE a.item = il.item and a.loc = il.loc) a ON a.rn = rn.rn;
结果:
+------+------+-----+-------+
| ITEM | LOC | QTY | ASSET |
+------+------+-----+-------+
| 500 | Loc1 | 5 | 7 |
| 500 | Loc1 | 5 | 8 |
| 500 | Loc1 | 5 | 9 |
| 500 | Loc1 | 5 | 10 |
| 500 | Loc1 | 5 | 11 |
| 501 | Loc2 | 2 | 27 |
| 501 | Loc2 | 2 | |
| 501 | Loc3 | 1 | |
+------+------+-----+-------+
答案 2 :(得分:0)
Alex和Matthew仅使用SQL成功地给出了解决方案。
我认为其他解决方案是创建数据库功能,该功能将管道您需要的所有行:
TYPE tp_r_item_loc_asset IS RECORD
(
item yuor_table_2.item%TYPE,
location yuor_table_2.location%TYPE,
qty yuor_table_2.qty%TYPE,
asset yuor_table_2.asset%TYPE
);
TYPE tp_a_item_loc_asset IS TABLE OF tp_r_item_loc_asset;
FUNCTION f_your_pipeline_funtion
RETURN tp_a_item_loc_asset
PIPELINED
IS
v_row tp_r_item_loc_asset;
v_asset NUMBER := null;
BEGIN
FOR i IN (SELECT item, location, qty
FROM your_table_1
ORDER BY item, location)
LOOP
FOR j in 1..i.qty
LOOP
BEGIN
SELECT asset
INTO v_asset
FROM yuor_table_2
WHERE item = i.item
AND location = i.location
ORDER BY asset ASC;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
v_asset := null;
END;
v_row.item := i.item;
v_row.location := i.location;
v_row.qty := 1;
v_row.asset := v_asset;
PIPE ROW (v_r_report_blob);
END LOOP;
END LOOP;
RETURN;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN;
END f_your_pipeline_funtion;
将所有内容放入包装中。
之后,您可以通过以下方式引用(从中选择):
SELECT item, location, qty, asset
FROM TABLE (p_your_package_name.f_your_pipeline_funtion());
我希望我也能提供帮助!