|
先贴一下目前的SQL, 真是个体力活!
WITH
o AS (SELECT '+' op,0 pr FROM DUAL UNION ALL SELECT '-',0 FROM DUAL UNION ALL SELECT '*',1 FROM DUAL UNION ALL SELECT '/',1 FROM DUAL)
,d AS (
SELECT 'A' C1,'B' C2,'C' C3,'D' C4,'E' C5,'F' C6 FROM DUAL
)
,d5 AS (
SELECT C1||o.op||C2 C1,C3 C2,C4 C3,C5 C4,C6 C5
,o.pr c1pr,TO_NUMBER(NULL) c2pr,TO_NUMBER(NULL) c3pr,TO_NUMBER(NULL) c4pr,TO_NUMBER(NULL) c5pr --- 操作符优先级
,'@ 2' pos1,'@' pos2,'@' pos3,'@' pos4,'@' pos5 ---- 操作符在表达式中出现的位置
FROM d,o
UNION ALL
SELECT C1,C2||o.op||C3 C2,C4 C3,C5 C4,C6 C5
,TO_NUMBER(NULL) c1pr,o.pr c2pr,TO_NUMBER(NULL) c3pr,TO_NUMBER(NULL) c4pr,TO_NUMBER(NULL) c5pr
,'@' pos1,'@ 2' pos2,'@' pos3,'@' pos4,'@' pos5
FROM d,o
UNION ALL
SELECT C1,C2,C3||o.op||C4 C3,C5 C4,C6 C5
,TO_NUMBER(NULL) c1pr,TO_NUMBER(NULL) c2pr,o.pr c3pr,TO_NUMBER(NULL) c4pr,TO_NUMBER(NULL) c5pr
,'@' pos1,'@' pos2,'@ 2' pos3,'@' pos4,'@' pos5
FROM d,o
UNION ALL
SELECT C1,C2,C3,C4||o.op||C5 C4,C6 C5
,TO_NUMBER(NULL) c1pr,TO_NUMBER(NULL) c2pr,TO_NUMBER(NULL) c3pr,o.pr c4pr,TO_NUMBER(NULL) c5pr
,'@' pos1,'@' pos2,'@' pos3,'@ 2' pos4,'@' pos5
FROM d,o
UNION ALL
SELECT C1,C2,C3,C4,C5||o.op||C6 C5
,TO_NUMBER(NULL) c1pr,TO_NUMBER(NULL) c2pr,TO_NUMBER(NULL) c3pr,TO_NUMBER(NULL) c4pr,o.pr c5pr
,'@' pos1,'@' pos2,'@' pos3,'@' pos4,'@ 2' pos5
FROM d,o
)
,d4 AS (
SELECT CASE WHEN c1pr<o.pr THEN '('||C1||')' ELSE C1 END
||o.op
||CASE WHEN c2pr<o.pr THEN '('||C2||')'
WHEN c2pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C2,DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))+1
,SUBSTR(pos2,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c2,SUBSTR(pos2,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)
||SUBSTR(C2,SUBSTR(pos2,-2)+1)
ELSE C2
END C1
,C3 C2,C4 C3,C5 C4
,o.pr c1pr,c3pr c2pr,c4pr c3pr,c5pr c4pr
,DECODE(c1pr,o.pr,pos1,'@')
||LPAD(LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c2pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos2,LEVEL*2,2)+LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)) pos1
,pos3 pos2,pos4 pos3,pos5 pos4
FROM d5,o
UNION
SELECT C1,
CASE WHEN c2pr<o.pr THEN '('||C2||')' ELSE C2 END
||o.op
||CASE WHEN c3pr<o.pr THEN '('||C3||')'
WHEN c3pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C3,DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))+1
,SUBSTR(pos3,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c3,SUBSTR(pos3,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)
||SUBSTR(C3,SUBSTR(pos3,-2)+1)
ELSE C3
END C2
,C4 C3,C5 C4
,c1pr,o.pr c2pr,c4pr c3pr,c5pr c4pr
,pos1
,DECODE(c2pr,o.pr,pos2,'@')
||LPAD(LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c3pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos3,LEVEL*2,2)+LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)) pos2
,pos4 pos3,pos5 pos4
FROM d5,o
UNION
SELECT C1,C2,
CASE WHEN c3pr<o.pr THEN '('||C3||')' ELSE C3 END
||o.op
||CASE WHEN c4pr<o.pr THEN '('||C4||')'
WHEN c4pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C4,DECODE(LEVEL,1,0,SUBSTR(pos4,LEVEL*2-2,2))+1
,SUBSTR(pos4,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos4,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c4,SUBSTR(pos4,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos4)/2)
||SUBSTR(C4,SUBSTR(pos4,-2)+1)
ELSE C4
END C3
,C5 C4
,c1pr,c2pr,o.pr c3pr,c5pr c4pr
,pos1,pos2
,DECODE(c3pr,o.pr,pos3,'@')
||LPAD(LENGTH(C3)+1+CASE WHEN c3pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c4pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos4,LEVEL*2,2)+LENGTH(C3)+1+CASE WHEN c3pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos4)/2)) pos3
,pos5 pos4
FROM d5,o
UNION
SELECT C1,C2,C3,
CASE WHEN c4pr<o.pr THEN '('||C4||')' ELSE C4 END
||o.op
||CASE WHEN c5pr<o.pr THEN '('||C5||')'
WHEN c5pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C5,DECODE(LEVEL,1,0,SUBSTR(pos5,LEVEL*2-2,2))+1
,SUBSTR(pos5,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos5,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c5,SUBSTR(pos5,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos5)/2)
||SUBSTR(C5,SUBSTR(pos5,-2)+1)
ELSE C5
END C4
,c1pr,c2pr,c3pr,o.pr c4pr
,pos1,pos2,pos3
,DECODE(c4pr,o.pr,pos4,'@')
||LPAD(LENGTH(C4)+1+CASE WHEN c4pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c5pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos5,LEVEL*2,2)+LENGTH(C4)+1+CASE WHEN c4pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos5)/2)) pos4
FROM d5,o
)
,d3 AS (
SELECT CASE WHEN c1pr<o.pr THEN '('||C1||')' ELSE C1 END
||o.op
||CASE WHEN c2pr<o.pr THEN '('||C2||')'
WHEN c2pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C2,DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))+1
,SUBSTR(pos2,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c2,SUBSTR(pos2,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)
||SUBSTR(C2,SUBSTR(pos2,-2)+1)
ELSE C2
END C1
,C3 C2,C4 C3
,o.pr c1pr,c3pr c2pr,c4pr c3pr
,DECODE(c1pr,o.pr,pos1,'@')
||LPAD(LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c2pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos2,LEVEL*2,2)+LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)) pos1
,pos3 pos2,pos4 pos3
FROM d4,o
UNION
SELECT C1,
CASE WHEN c2pr<o.pr THEN '('||C2||')' ELSE C2 END
||o.op
||CASE WHEN c3pr<o.pr THEN '('||C3||')'
WHEN c3pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C3,DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))+1
,SUBSTR(pos3,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c3,SUBSTR(pos3,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)
||SUBSTR(C3,SUBSTR(pos3,-2)+1)
ELSE C3
END C2
,C4 C3
,c1pr,o.pr c2pr,c4pr c3pr
,pos1
,DECODE(c2pr,o.pr,pos2,'@')
||LPAD(LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c3pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos3,LEVEL*2,2)+LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)) pos2
,pos4 pos3
FROM d4,o
UNION
SELECT C1,C2,
CASE WHEN c3pr<o.pr THEN '('||C3||')' ELSE C3 END
||o.op
||CASE WHEN c4pr<o.pr THEN '('||C4||')'
WHEN c4pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C4,DECODE(LEVEL,1,0,SUBSTR(pos4,LEVEL*2-2,2))+1
,SUBSTR(pos4,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos4,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c4,SUBSTR(pos4,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos4)/2)
||SUBSTR(C4,SUBSTR(pos4,-2)+1)
ELSE C4
END C3
,c1pr,c2pr,o.pr c3pr
,pos1,pos2
,DECODE(c3pr,o.pr,pos3,'@')
||LPAD(LENGTH(C3)+1+CASE WHEN c3pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c4pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos4,LEVEL*2,2)+LENGTH(C3)+1+CASE WHEN c3pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos4)/2)) pos3
FROM d4,o
)
,d2 AS (
SELECT CASE WHEN c1pr<o.pr THEN '('||C1||')' ELSE C1 END
||o.op
||CASE WHEN c2pr<o.pr THEN '('||C2||')'
WHEN c2pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C2,DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))+1
,SUBSTR(pos2,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c2,SUBSTR(pos2,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)
||SUBSTR(C2,SUBSTR(pos2,-2)+1)
ELSE C2
END C1
,C3 C2
,o.pr c1pr,c3pr c2pr
,DECODE(c1pr,o.pr,pos1,'@')
||LPAD(LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c2pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos2,LEVEL*2,2)+LENGTH(C1)+1+CASE WHEN c1pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)) pos1
,pos3 pos2
FROM d3,o
UNION
SELECT C1,
CASE WHEN c2pr<o.pr THEN '('||C2||')' ELSE C2 END
||o.op
||CASE WHEN c3pr<o.pr THEN '('||C3||')'
WHEN c3pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C3,DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))+1
,SUBSTR(pos3,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos3,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c3,SUBSTR(pos3,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)
||SUBSTR(C3,SUBSTR(pos3,-2)+1)
ELSE C3
END C2
,c1pr,o.pr c2pr
,pos1
,DECODE(c2pr,o.pr,pos2,'@')
||LPAD(LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)
||DECODE(c3pr,o.pr,(SELECT LISTAGG(LPAD(SUBSTR(pos3,LEVEL*2,2)+LENGTH(C2)+1+CASE WHEN c2pr<o.pr THEN 2 ELSE 0 END,2)) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos3)/2)) pos2
FROM d3,o
)
SELECT DISTINCT
CASE WHEN c1pr<o.pr THEN '('||C1||')' ELSE C1 END
||o.op
||CASE WHEN c2pr<o.pr THEN '('||C2||')'
WHEN c2pr=o.pr AND o.op IN ('-','/') THEN
(SELECT LISTAGG(SUBSTR(C2,DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))+1
,SUBSTR(pos2,LEVEL*2,2) - DECODE(LEVEL,1,0,SUBSTR(pos2,LEVEL*2-2,2))-1
)
||TRANSLATE(SUBSTR(c2,SUBSTR(pos2,LEVEL*2,2),1),'+-*/','-+/*')
) WITHIN GROUP(ORDER BY LEVEL) FROM DUAL CONNECT BY LEVEL<LENGTH(pos2)/2)
||SUBSTR(C2,SUBSTR(pos2,-2)+1)
ELSE C2
END C1
FROM d2,o;
|
|