正如mathguy指出的那样,递归类将允许这样做内联。因为在这里没有,如果你的情况允许使用pl/sql
(我无法从你的帖子中知道),或许值得考虑放入pl/sql
并程序化地评估数据集。
它可能仍然是可能的,而不诉诸于pl/sql
但没有递归子因子,属性之间的混合行内和行间关系似乎不太可能。这不太好,但是这里有一个例子,在你的文章中用一个函数生成你期望的输出。
有在这个例子中的一些注意事项:
- 甲骨文不承认空字符串,如您表示应该 出现在
REQD
时不'reqd'
。我在这里使用了NULL
。
- 由于
ADJUST
的值用于计算CL_QTY
,NULL
无效。对于前四条记录,CL_QTY
使用0
的固定ADJUST
而不是显示的NULL
。我建议明确使用0
代替ADJUST
的前四个值,而不是NULL
。
- 我不知道这里是什么在 要求,即“需要1个值”的意思 -“调整>会后需要4纪录= 1的值 开始”。在这个例子中,我把它意味着“是尚未在
ADJUST
使用 NEED
的最后一个值(2条)之前,”
- 本示例假设行级条件应是确定和排序由
DAY
。如果排序顺序不同,则需要更新光标。
有了这样说,这里是你介绍的是使用function
一个方法,你可以用它来复制所需的数据表的例子:
首先创建测试数据:
CREATE TABLE DAY_QUANTITY(
DAY NUMBER,
QTY NUMBER
);
INSERT INTO DAY_QUANTITY VALUES (0,NULL);
INSERT INTO DAY_QUANTITY VALUES (1,1);
INSERT INTO DAY_QUANTITY VALUES (2,1);
INSERT INTO DAY_QUANTITY VALUES (3,0);
INSERT INTO DAY_QUANTITY VALUES (4,0);
INSERT INTO DAY_QUANTITY VALUES (5,2);
INSERT INTO DAY_QUANTITY VALUES (6,1);
INSERT INTO DAY_QUANTITY VALUES (7,1);
INSERT INTO DAY_QUANTITY VALUES (8,3);
然后TYPE
返回:
CREATE OR REPLACE TYPE QTY_ADJUST_REC IS OBJECT(DAY NUMBER, QTY NUMBER, OP_QTY NUMBER, CL_QTY NUMBER, REQD VARCHAR2(10), NEED NUMBER, ADJUST NUMBER);
/
CREATE OR REPLACE TYPE QTY_ADJUST_TAB IS TABLE OF QTY_ADJUST_REC;
/
而且FUNCTION
。这将通过数据迭代和应用规则,因为他们成为合格:
CREATE OR REPLACE FUNCTION QTY_ADJUST
RETURN QTY_ADJUST_TAB
IS
V_ITERATION_COUNT NUMBER := 0;
V_CL_QTY NUMBER := 3;
V_NEED NUMBER := NULL;
V_OP_QTY NUMBER := NULL;
V_REQD VARCHAR2(10) := NULL;
V_ADJUST NUMBER := NULL;
V_QTY_ADJUST_REC QTY_ADJUST_REC;
V_QTY_ADJUST_TAB QTY_ADJUST_TAB;
BEGIN
V_QTY_ADJUST_TAB := QTY_ADJUST_TAB();
FOR POINTER IN (SELECT
DAY,
QTY
FROM DAY_QUANTITY
ORDER BY DAY ASC)
LOOP
V_ITERATION_COUNT := V_ITERATION_COUNT + 1;
IF V_QTY_ADJUST_TAB.COUNT() > 0
THEN
V_OP_QTY := V_QTY_ADJUST_TAB(V_QTY_ADJUST_TAB.COUNT()).CL_QTY;
V_CL_QTY := (V_QTY_ADJUST_TAB(V_QTY_ADJUST_TAB.COUNT()).CL_QTY
- POINTER.QTY
+ CASE WHEN V_ITERATION_COUNT < 5 THEN 0 ELSE
COALESCE(V_QTY_ADJUST_TAB(V_QTY_ADJUST_TAB.COUNT() - 1).NEED, 0) END);
END IF;
IF V_ITERATION_COUNT > 2
THEN
V_REQD := CASE WHEN V_CL_QTY < 2
THEN 'reqd'
ELSE NULL END;
V_NEED := CASE WHEN V_CL_QTY < 2
THEN (4 - V_CL_QTY)
ELSE 0 END;
END IF;
IF V_ITERATION_COUNT > 4
THEN
V_ADJUST := V_QTY_ADJUST_TAB(V_QTY_ADJUST_TAB.COUNT() - 1).NEED;
END IF;
V_QTY_ADJUST_REC := QTY_ADJUST_REC(POINTER.DAY, POINTER.QTY, V_OP_QTY, V_CL_QTY, V_REQD, V_NEED, V_ADJUST);
V_QTY_ADJUST_TAB.EXTEND();
V_QTY_ADJUST_TAB(V_QTY_ADJUST_TAB.COUNT()) := V_QTY_ADJUST_REC;
V_CL_QTY := NULL;
V_REQD := NULL;
V_NEED := NULL;
V_ADJUST := NULL;
END LOOP;
RETURN V_QTY_ADJUST_TAB;
END;
/
Function QTY_ADJUST compiled
然后对其进行测试:
SELECT * FROM TABLE(QTY_ADJUST()) ORDER BY 1 ASC;
DAY QTY OP_QTY CL_QTY REQD NEED ADJUST
0 3
1 1 3 2
2 1 2 1 reqd 3
3 0 1 1 reqd 3
4 0 1 4 0 3
5 2 4 5 0 3
6 1 5 4 0 0
7 1 4 3 0 0
8 3 3 0 reqd 4 0
编辑:在回答你的要求提供额外subfactoring解决方案,这里是一个替代例如使用递归CTE。
这与上述过程方法在机械上类似 - 它以迭代方式构建结果集 - 但是使用SQL来代替。
这个例子可以做一些重构,但希望给出一个递归子因子可以工作的一种方法的例子(请注意,还有其他方式来生成这种类型的数据,以及使用这种类型的查询)。
使用从上述PL/SQL
例子相同DAY_QUANTITY
表和数据,这里的子因素的一个例子采用同样的处理,以将数据:
WITH NUMBERED_DAY_QTY(DAY, QTY, NUMBERED_ROW) AS (
SELECT
DAY_QUANTITY.DAY,
DAY_QUANTITY.QTY,
ROW_NUMBER()
OVER (
PARTITION BY NULL
ORDER BY DAY_QUANTITY.DAY ASC) - 1 AS NUMBERED_ROW
FROM DAY_QUANTITY),
DAY_QTY_ITER(DAY, QTY, NUMBERED_ROW, OP_QTY, CL_QTY, REQD, NEED, ADJUST, NEED_POINTER, ITERATION_LEVEL)
AS (
SELECT
DAY,
QTY,
NUMBERED_ROW,
CAST(NULL AS NUMBER) AS OP_QTY,
3 AS CL_QTY,
NULL AS REQD,
CAST(NULL AS NUMBER) AS NEED,
CAST(NULL AS NUMBER) AS ADJUST,
CAST(NULL AS NUMBER) AS NEED_POINTER,
1 AS ITERATION_LEVEL
FROM NUMBERED_DAY_QTY
WHERE DAY = 0
UNION ALL
SELECT
NUMBERED_DAY_QTY.DAY,
NUMBERED_DAY_QTY.QTY,
NUMBERED_DAY_QTY.NUMBERED_ROW,
DAY_QTY_ITER.CL_QTY AS OP_QTY,
(DAY_QTY_ITER.CL_QTY - NUMBERED_DAY_QTY.QTY +
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 4
THEN 0
ELSE COALESCE(DAY_QTY_ITER.NEED_POINTER, 0) END) AS CL_QTY,
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 2
THEN NULL
ELSE CASE WHEN (DAY_QTY_ITER.CL_QTY - NUMBERED_DAY_QTY.QTY +
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 4
THEN 0
ELSE COALESCE(DAY_QTY_ITER.NEED_POINTER, 0) END) < 2
THEN 'reqd'
ELSE NULL END END AS REQD,
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 2
THEN NULL
ELSE CASE WHEN (DAY_QTY_ITER.CL_QTY - NUMBERED_DAY_QTY.QTY +
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 4
THEN 0
ELSE COALESCE(DAY_QTY_ITER.NEED_POINTER, 0) END) < 2
THEN (4 - (DAY_QTY_ITER.CL_QTY - NUMBERED_DAY_QTY.QTY +
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 4
THEN 0
ELSE COALESCE(DAY_QTY_ITER.NEED_POINTER, 0) END))
ELSE 0 END END AS NEED,
CASE WHEN DAY_QTY_ITER.ITERATION_LEVEL < 4
THEN NULL
ELSE
COALESCE(DAY_QTY_ITER.NEED_POINTER, 0) END AS ADJUST,
DAY_QTY_ITER.NEED AS NEED_POINTER,
DAY_QTY_ITER.ITERATION_LEVEL + 1 AS ITERATION_LEVEL
FROM NUMBERED_DAY_QTY
INNER JOIN DAY_QTY_ITER ON NUMBERED_DAY_QTY.NUMBERED_ROW = DAY_QTY_ITER.ITERATION_LEVEL)
SELECT
DAY, QTY, OP_QTY, CL_QTY, REQD, NEED, ADJUST
FROM DAY_QTY_ITER
ORDER BY 1 ASC;
然后对其进行测试:
DAY QTY OP_QTY CL_QTY REQD NEED ADJUST
0 3
1 1 3 2
2 1 2 1 reqd 3
3 0 1 1 reqd 3
4 0 1 4 0 3
5 2 4 5 0 3
6 1 5 4 0 0
7 1 4 3 0 0
8 3 3 0 reqd 4 0
9 rows selected.
提供SQL – SaggingRufus
显示迄今为止尝试的内容。 –
需求中出现问题。 “你会在第四张唱片后开始”是什么意思?也许你的意思是前三行有0,但你显示NULL。这意味着对于第2,3,4行,CL_Qty的结果将为NULL。请澄清。 – mathguy