挑战Oracle PL/SQL—将一列分配给另一个排序列的排列
输入是G系列和p系列的两个数据集,它们是实际数据中的字符串挑战Oracle PL/SQL—将一列分配给另一个排序列的排列,sql,oracle,algorithm,plsql,permutation,Sql,Oracle,Algorithm,Plsql,Permutation,输入是G系列和p系列的两个数据集,它们是实际数据中的字符串 X = 3, G series G1 G2 G3 Y = 2, P series P1 P2 G系列的X个数始终大于等于p系列的Y个数 我想将所有可能匹配的可用p值返回到G值,除了所有相同的p值都分配给G。在每个组中,G值的顺序是固定的,始终是G1、G2、G3 预期结果之一: 1 G1 P1 1 G2 P1 1 G3 P2 --------------- 2 G1 P2
X = 3,
G series
G1
G2
G3
Y = 2,
P series
P1
P2
G系列的X个数始终大于等于p系列的Y个数
我想将所有可能匹配的可用p值返回到G值,除了所有相同的p值都分配给G。在每个组中,G值的顺序是固定的,始终是G1、G2、G3
预期结果之一:
1 G1 P1
1 G2 P1
1 G3 P2
---------------
2 G1 P2
2 G2 P2
2 G3 P1
---------------
3 G1 P1
3 G2 P2
3 G3 P1
---------------
4 G1 P2
4 G2 P1
4 G3 P2
---------------
5 G1 P1
5 G2 P2
5 G3 P2
---------------
6 G1 P2
6 G2 P1
6 G3 P1
如你所见,对于X=3,Y=2,我想要6组或X*Y组可能的配对排列:
| Group 1 | Group 2 | Group 3 | Group 4 | Group 5 | Group 6 |
-----------------------------------------------------------
| G1 P1 | G1 P2 | G1 P1 | G1 P2 | G1 P1 | G1 P2 |
| G2 P1 | G2 P2 | G2 P2 | G2 P1 | G2 P2 | G2 P1 |
| G3 P2 | G3 P1 | G3 P1 | G3 P2 | G3 P2 | G3 P1 |
G1-G3的p值模式:
换句话说,需要像1122211121212122211这样的P的组合。
但不需要111222个P值。可以对六组进行任何排序,只要排列都已列出
不需要以下类似的组合,因为所有相同的p都分配给同一组中的G:
1 G1 P1
1 G2 P1
1 G3 P1
-----------
2 G1 P2
2 G2 P2
2 G3 P2
我的计划:
首先对两个数据集进行笛卡尔积:
1 G1 P1
2 G1 P2
3 G2 P1
4 G2 P2
5 G3 P1
6 G3 P2
然后插入X个笛卡尔积,并希望创建笛卡尔积组合序列以获得预期结果,但我无法从中找到模式
1 G1 P1
2 G2 P1
3 G3 P2
4 G1 P2
5 G2 P2
6 G3 P1
7 G1 P1
8 G2 P2
9 G3 P1
10 G1 P2
11 G2 P1
12 G3 P2
13 G1 P1
14 G2 P2
15 G3 P2
16 G1 P2
17 G2 P1
18 G3 P1
另外,您可能会注意到可能的结果有X*(Y^X-Y)行,在上面的情况下,当X=3和Y=2时,它是3*(2^3-2)=18行和6组或(Y^X-Y)
此过程创建不需要的序列:
Create or replace Procedure Permutation ( X in Number, Y in Number )
AS j Number:=1;
Begin
For k in 1 .. X
Loop
For i in 1 .. X*Y
Loop
CASE
WHEN i = 1 THEN
Insert into Table_1 ("INJECTION") values ( j );
Commit;
WHEN mod(i,2)= 0 Then
j := j + X ;
Insert into Table_1 ("INJECTION") values ( j );
Commit;
WHEN mod(i,2)<>0 then
j := j - Y ;
Insert into Table_1 ("INJECTION") values ( j );
Commit;
End CASE;
End Loop;
j := j + 1;
Commit;
End Loop;
EXCEPTION
WHEN OTHERS
THEN
null;
End;
1 G1 P1 1
3 G2 P1 2
5 G3 P1 3
2 G1 P2 4
4 G2 P2 5
6 G3 P2 6
7 G1 P1 7
9 G2 P1 8
11 G3 P1 9
8 G1 P2 10
10 G2 P2 11
12 G3 P2 12
13 G1 P1 13
15 G2 P1 14
17 G3 P1 15
14 G1 P2 16
16 G2 P2 17
18 G3 P2 18
做一个数字排序,你有以下,正是结果不想要的:
Create or replace Procedure Permutation ( X in Number, Y in Number )
AS j Number:=1;
Begin
For k in 1 .. X
Loop
For i in 1 .. X*Y
Loop
CASE
WHEN i = 1 THEN
Insert into Table_1 ("INJECTION") values ( j );
Commit;
WHEN mod(i,2)= 0 Then
j := j + X ;
Insert into Table_1 ("INJECTION") values ( j );
Commit;
WHEN mod(i,2)<>0 then
j := j - Y ;
Insert into Table_1 ("INJECTION") values ( j );
Commit;
End CASE;
End Loop;
j := j + 1;
Commit;
End Loop;
EXCEPTION
WHEN OTHERS
THEN
null;
End;
1 G1 P1 1
3 G2 P1 2
5 G3 P1 3
2 G1 P2 4
4 G2 P2 5
6 G3 P2 6
7 G1 P1 7
9 G2 P1 8
11 G3 P1 9
8 G1 P2 10
10 G2 P2 11
12 G3 P2 12
13 G1 P1 13
15 G2 P1 14
17 G3 P1 15
14 G1 P2 16
16 G2 P2 17
18 G3 P2 18
我想知道是否有更好的方法来处理这个问题?
阵列?级别
感谢您的投入,非常感谢
更新: 我在考虑算法,本质上,它是关于从 一个P数组
[P1,P2,P3,…PY]
进入G阵列[G1、G2、G3…GX]
Python 3.5.2,
Create When X = 3, Y = 2, p = [1,2]
这正是我想要的结果,除了所有重复项,(1,1,1)和(2,2,2)…。我建议建立一种分支树。每次你添加一个“G”,你的树实际上会增加一个等级 您希望以有序方式得到的结果是到树叶子的路径,除了外部路径(下图) 每次添加一个级别时,复制每个p的元组,并将每个p添加到同一级别。这里有一种在这样一个数组(
l_ttab
)中构建它的方法,您可以删除第一个和最后一个元素(+与每个G的叉积),以满足您的需要
类型
复制功能cpy\u节点
:
从“P”函数的输入列表中生成一个表cto\u表
:
创建*有序节点列表:
*我并不是说上面的方法是最优的,因为我每次都会重新复制树,但这样做对我来说更容易。我建议构建一种分支树。每次你添加一个“G”,你的树实际上会增加一个等级 您希望以有序方式得到的结果是到树叶子的路径,除了外部路径(下图) 每次添加一个级别时,复制每个p的元组,并将每个p添加到同一级别。这里有一种在这样一个数组(
l_ttab
)中构建它的方法,您可以删除第一个和最后一个元素(+与每个G的叉积),以满足您的需要
类型
复制功能cpy\u节点
:
从“P”函数的输入列表中生成一个表cto\u表
:
创建*有序节点列表:
*我并不是说上面的方法是最优的,因为我每次都会重新复制树,但这样做对我来说更容易。您需要澄清您的要求。预期结果的前五行与不需要的组合的前五行完全相同。这两张名单有什么不同?谢谢你的评论,克里斯蒂安。如果您再看一看,可能会注意到不想要的结果在同一组中具有与G1、G2、G3匹配的相同P值,例如G1P1、G2P1、G3P1和G1P2、G2P2、G3P2。预期结果为G1P1、G2P1、G3P2等组;P值在组中并不完全相同。也许您需要定义组的含义?我看到像G1P1和G2P1这样的配对在通缉名单和非通缉名单中出现了不止一次,你的问题中没有任何东西可以解释这种情况。是的,我刚刚修改了这个问题,希望它更容易理解。在每个组中,所有G值都是按固定顺序排列的,G1、G2、G3,我想将P值与每个G值配对,不包括像G1 P1、G2 P1、G3 P1这样的配对。和g1p2,g2p2,g3p2。谢谢你的耐心,Christian。好的,如果X=3,Y=2,你需要六组。每组应包含G(可能值1..X)和P(可能值1..Y)的可能组合。任何组合都是有效的。但是,在一个组中,任何两个组合都不应相同,并且必须至少有两个不同的P值?您需要澄清您的要求。预期结果的前五行与不需要的组合的前五行完全相同。这两张名单有什么不同?谢谢你的评论,克里斯蒂安。如果您再看一看,可能会注意到不想要的结果在同一组中具有与G1、G2、G3匹配的相同P值,例如G1P1、G2P1、G3P1和G1P2、G2P2、G3P2。预期结果为G1P1、G2P1、G3P2等组;P值在组中并不完全相同。也许您需要定义组的含义?我看到像G1P1和G2P1这样的配对在通缉名单和非通缉名单中出现了不止一次,你的问题中没有任何东西可以解释这种情况。是的,我刚刚修改了这个问题,希望它更容易理解。在每个组中,所有G值都是按固定顺序排列的,G1、G2、G3,我想将P值与每个G值配对,不包括像G1 P1、G2 P1、G3 P1这样的配对。和g1p2,g2p2,g3p2。谢谢你的耐心,Christian。好的,如果X=3,Y=2,你需要六组。每组应包含一个可能的G(possib)组合
(1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 2, 2)
(2, 1, 1)
(2, 1, 2)
(2, 2, 1)
(2, 2, 2)
G1 G2 G3
p1 ****************NO (p1 p1 p1)
/
p1
/ \
/ p2 (p1 p1 p2)
p1
\ p1 (p1 p2 p1)
\ /
p2
\
p2 (p1 p2 p2)
p1 (p2 p1 p1)
/
p1
/ \
/ p2 (p2 p1 p2)
p2
\ p1 (p2 p2 p1)
\ /
p2
\
p2 **************NO (p2 p2 p1)
CREATE OR REPLACE TYPE t_list AS TABLE OF VARCHAR2(100);
CREATE OR REPLACE TYPE tt_list AS TABLE OF t_list;
CREATE OR REPLACE FUNCTION cpy_node(p_list in t_list)
RETURN t_list
AS
l_tab t_list := t_list();
BEGIN
for i in 1..p_list.count loop
l_tab.extend;
l_tab(i):=p_list(i);
end loop;
RETURN l_tab;
END cpy_node;
CREATE OR REPLACE FUNCTION cto_table(p_sep in Varchar2, p_list IN VARCHAR2)
RETURN t_list
AS
l_string VARCHAR2(32767) := p_list || p_sep;
l_sep_index PLS_INTEGER;
l_index PLS_INTEGER := 1;
l_tab t_list := t_list();
BEGIN
LOOP
l_sep_index := INSTR(l_string, p_sep, l_index);
EXIT
WHEN l_sep_index = 0;
l_tab.EXTEND;
l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_sep_index - l_index));
l_index := l_sep_index + 1;
END LOOP;
RETURN l_tab;
END cto_table;
declare
l_ttab tt_list :=tt_list();
l_ttab_next tt_list :=tt_list();
l_tab_p t_list;
l_tab t_list;
p_nb_lvl pls_integer:=2;
begin
l_tab_p := cto_table(',', 'p1, p2');
-- initiate table with single nodes
for i in 1..l_tab_p.count loop
l_ttab.extend;
l_tab :=t_list();
l_tab.extend;
l_tab(l_tab.count):=l_tab_p(i);
l_ttab(l_ttab.count):=l_tab;
end loop;
-- ( p1 ) ( p2 )
for k in 1..p_nb_lvl-1 loop
l_ttab_next := tt_list();
for j in 1..l_ttab.count loop
for i in 1..l_tab_p.count loop
-- copy from current list
l_ttab_next.extend;
l_ttab_next(l_ttab_next.count):=cpy_node(l_ttab(j));
-- add node at the end
l_ttab_next(l_ttab_next.count).extend;
l_ttab_next(l_ttab_next.count)(k+1):=l_tab_p(i);
end loop;
end loop;
l_ttab := l_ttab_next;
end loop;
-- display result
for i in 1..l_ttab.count loop
for j in 1..l_ttab(i).count loop
dbms_output.put(l_ttab(i)(j)||' ');
end loop;
dbms_output.put_line(chr(13)||'--');
end loop;
-- e.g. if p_nb_lvl=2:
--(p1 p1) (p1 p2) (p2 p1) (p2 p2) (p1 p1) (p1 p2) ( p2 p1) ( p2 p2)
end;