有没有像Python的Python列表zip函数这样的集合在Oracle SQL中?



在重构一些复杂的PL/SQL包以提高性能时,有几次我遇到了以下情况:

输入:两个相同长度的 PL/SQL VARRAY A 和 B 或表(例如,SYS。ODCIVarchar2List(,例如

A := SYS.ODCIVarchar2List('Summer', 'Winter');
B := SYS.ODCIVarchar2List('hot', 'cold');

(给定索引处的列表中的条目相互对应(。

现在,我有一个或多或少复杂的SQL语句(例如MERGE INTO(,我需要假设的"zip(A,B("作为输入。

到目前为止,我找到的唯一解决方案是这样的结构:

with t1 as (select rownum rn, column_value as season from table(:A))
, t2 as (select rownum rn, column_value as temperature from table(:B))
, input as (select t1.season, t2.temperature
from t1, t2
where t1.rn = t2.rn
)
-- Now do something with the input. For demonstration purpose, just show it:
select * from input;

这有效,但对于如此简单的任务来说似乎过于复杂。

有没有更好的解决方案?

备注: 我知道关于"从表中选择"顺序的理论不确定性(...(。这一直有效,所以我们不要在这里讨论它,直到有一天有人可以展示一个它不起作用的例子。

作为旁注(并进一步澄清问题(:在 Python 中,我可以这样做:

L=[1,2]
M=["A","B"]
list(zip(L,M))

这将返回一个与 L 和 M 长度相同的列表,其中条目组合在一起:

[(1, 'A'), (2, 'B')]

我需要的是SQL中的类似的东西。

这可以在SQL中使用MODEL子句完成。这有点棘手,但非常有效...这是代码:

WITH
lists AS
(
Select 'Summer, Winter' "L", 'Hot, Cold' "M" From Dual 
),
mdl AS
(
SELECT
INDX, L, M,
L_LIST,
M_LIST
FROM
lists
MODEL
DIMENSION BY (0 as INDX)
MEASURES (L, M, REPLACE(L, ', ', ',') as L_LIST, REPLACE(M, ', ', ',') as M_LIST)
RULES ITERATE(2)
(
L[ITERATION_NUMBER + 1] = SubStr(L_LIST[ITERATION_NUMBER], 1, CASE WHEN InStr(L_LIST[ITERATION_NUMBER], ',') = 0 THEN 100
          ELSE InStr(L_LIST[ITERATION_NUMBER], ',', ITERATION_NUMBER + 1) - 1 
          END),
L_LIST[ITERATION_NUMBER + 1] = SubStr(REPLACE(L_LIST[ITERATION_NUMBER], L[ITERATION_NUMBER + 1], ''), 2),
M[ITERATION_NUMBER + 1] = SubStr(M_LIST[ITERATION_NUMBER], 1, CASE WHEN InStr(M_LIST[ITERATION_NUMBER], ',') = 0 THEN 100
          ELSE InStr(M_LIST[ITERATION_NUMBER], ',', ITERATION_NUMBER + 1) - 1 
          END),
M_LIST[ITERATION_NUMBER + 1] = SubStr(REPLACE(M_LIST[ITERATION_NUMBER], M[ITERATION_NUMBER + 1], ''), 2)
)       
),
combined AS
(
SELECT
INDX,
SubStr(LISTAGG(L || ',', ',') WITHIN GROUP (ORDER BY INDX) || ' ' || LISTAGG(M || ',', ',') WITHIN GROUP (ORDER BY INDX),
1, Length(LISTAGG(L || ',', ',') WITHIN GROUP (ORDER BY INDX) || ' ' || LISTAGG(M || ',', ',') WITHIN GROUP (ORDER BY INDX)) - 1) "LIST"
FROM
mdl
WHERE
INDX > 0
GROUP BY
INDX, L, M
)
SELECT
'[' || LISTAGG('(' || LIST || ')', ', ') WITHIN GROUP (ORDER BY INDX) || ']' "ZIPPED_LIST"
FROM
combined
-- 
-- Result
-- 
-- ZIPPED_LIST
-- [(Summer, Hot), (Winter, Cold)]

最新更新