|
|
替你翻译成ORACLE语法(11GR2以上):
With
CARDS (n) As
(
--Select 1 FROM DUAL Union All Select 2 FROM DUAL Union All Select 3 FROM DUAL Union All Select 4 FROM DUAL
--Select 1 FROM DUAL Union All Select 4 FROM DUAL Union All Select 5 FROM DUAL Union All Select 6 FROM DUAL
--Select 3 FROM DUAL Union All Select 5 FROM DUAL Union All Select 6 FROM DUAL Union All Select 9 FROM DUAL
--Select 2 FROM DUAL Union All Select 7 FROM DUAL Union All Select 8 FROM DUAL Union All Select 9 FROM DUAL
Select 5 FROM DUAL Union All Select 5 FROM DUAL Union All Select 5 FROM DUAL Union All Select 5 FROM DUAL
--Select 4 FROM DUAL Union All Select 4 FROM DUAL Union All Select 10 FROM DUAL Union All Select 10 FROM DUAL
--Select 3 FROM DUAL Union All Select 3 FROM DUAL Union All Select 8 FROM DUAL Union All Select 8 FROM DUAL
-- WIKI 中的经典题目
--Select 1 FROM DUAL Union All Select 5 FROM DUAL Union All Select 5 FROM DUAL Union All Select 5 FROM DUAL
--Select 2 FROM DUAL Union All Select 4 FROM DUAL Union All Select 10 FROM DUAL Union All Select 10 FROM DUAL
--Select 2 FROM DUAL Union All Select 5 FROM DUAL Union All Select 5 FROM DUAL Union All Select 10 FROM DUAL
--Select 2 FROM DUAL Union All Select 7 FROM DUAL Union All Select 7 FROM DUAL Union All Select 10 FROM DUAL
--Select 3 FROM DUAL Union All Select 3 FROM DUAL Union All Select 7 FROM DUAL Union All Select 7 FROM DUAL
--Select 4 FROM DUAL Union All Select 4 FROM DUAL Union All Select 7 FROM DUAL Union All Select 7 FROM DUAL
--Select 2 FROM DUAL Union All Select 2 FROM DUAL Union All Select 11 FROM DUAL Union All Select 11 FROM DUAL
--Select 2 FROM DUAL Union All Select 2 FROM DUAL Union All Select 13 FROM DUAL Union All Select 13 FROM DUAL
--Select 1 FROM DUAL Union All Select 3 FROM DUAL Union All Select 4 FROM DUAL Union All Select 6 FROM DUAL
--Select 2 FROM DUAL Union All Select 3 FROM DUAL Union All Select 5 FROM DUAL Union All Select 12 FROM DUAL
--Select 1 FROM DUAL Union All Select 3 FROM DUAL Union All Select 9 FROM DUAL Union All Select 10 FROM DUAL
--Select 7 FROM DUAL Union All Select 8 FROM DUAL Union All Select 8 FROM DUAL Union All Select 10 FROM DUAL
--Select 9 FROM DUAL Union All Select 11 FROM DUAL Union All Select 12 FROM DUAL Union All Select 12 FROM DUAL
--Select 1 FROM DUAL Union All Select 2 FROM DUAL Union All Select 7 FROM DUAL Union All Select 7 FROM DUAL
--Select 3 FROM DUAL Union All Select 8 FROM DUAL Union All Select 8 FROM DUAL Union All Select 10 FROM DUAL
--Select 4 FROM DUAL Union All Select 8 FROM DUAL Union All Select 8 FROM DUAL Union All Select 11 FROM DUAL
--Select 5 FROM DUAL Union All Select 10 FROM DUAL Union All Select 10 FROM DUAL Union All Select 13 FROM DUAL
--Select 1 FROM DUAL Union All Select 5 FROM DUAL Union All Select 11 FROM DUAL Union All Select 11 FROM DUAL
--Select 1 FROM DUAL Union All Select 6 FROM DUAL Union All Select 11 FROM DUAL Union All Select 13 FROM DUAL
--Select 1 FROM DUAL Union All Select 7 FROM DUAL Union All Select 13 FROM DUAL Union All Select 13 FROM DUAL
),
OP (ID, OPER, PRIO) As
(
Select 1, '+', 1 FROM DUAL Union
Select 2, '-', 1 FROM DUAL Union
Select 3, '*', 0 FROM DUAL Union
Select 4, '/', 0 FROM DUAL Union
Select 5, '-', 1 FROM DUAL Union -- b - a
Select 6, '/', 0 FROM DUAL -- b / a
),
CARD1 (EXPR, VAL, PRIO, MASK, USED, OPER) As
(
Select Cast(n As Varchar2(10)), Cast(n As Decimal(18, 4)), 0,
Power(2, ROW_NUMBER() Over (Order By n) - 1), 1, '' From CARDS
),
CARD2 (EXPR, VAL, PRIO, MASK, USED, OPER) As
(
Select Distinct
C1.EXPR || OP.OPER || C2.EXPR,
Cast(Case OP.ID
When 1 Then C1.VAL + C2.VAL
When 2 Then C1.VAL - C2.VAL
When 3 Then C1.VAL * C2.VAL
When 4 Then Case When C2.VAL = 0 Then Power(20, 4) Else C1.VAL / C2.VAL End ----可以在WHERE里面过滤掉除数为0的情况
End As Decimal(18, 4)) VAL,
OP.PRIO,
C1.MASK + C2.MASK MASK,
C1.USED + C2.USED, --------- counter 用了多少操作数
OP.OPER
From CARD1 C1, OP, CARD1 C2
Where BITAND(C1.MASK, C2.MASK) = 0
And OP.ID In (1,2,3,4)
And (OP.ID Not In (1,3) Or (C1.MASK < C2.MASK))
),
CARD12 (EXPR, VAL, PRIO, MASK, USED, OPER) As
(
Select EXPR, VAL, PRIO, MASK, USED, OPER From CARD1
Union
Select EXPR, VAL, PRIO, MASK, USED, OPER From CARD2
),
POINT (EXPR, VAL, PRIO, MASK, USED, OPER) As
(
Select Cast(EXPR As Varchar2(10)), VAL, PRIO, MASK, USED, OPER From CARD2
Union All
Select
Cast(Case When OP.ID Not In (5, 6) Then
Case When C1.OPER IS NOT NULL And C1.PRIO > OP.PRIO
Then '(' || C1.EXPR || ')' Else C1.EXPR End
|| OP.OPER ||
Case When C2.OPER IS NOT NULL And (C2.PRIO > OP.PRIO Or (C2.PRIO = OP.PRIO And OP.ID Not In (1, 3)))
Then '(' || C2.EXPR || ')' Else C2.EXPR End
Else
Case When C2.OPER IS NOT NULL And C2.PRIO > OP.PRIO
Then '(' || C2.EXPR || ')' Else C2.EXPR End
|| OP.OPER ||
Case When C1.OPER IS NOT NULL And (C1.PRIO > OP.PRIO Or (C1.PRIO = OP.PRIO And OP.ID Not In (1, 3)))
Then '(' || C1.EXPR || ')' Else C1.EXPR End
End As Varchar2(10)) EXPR,
Cast(Case OP.ID
When 1 Then C1.VAL + C2.VAL
When 2 Then C1.VAL - C2.VAL
When 3 Then C1.VAL * C2.VAL
When 4 Then Case When C2.VAL = 0 Then Power(20, 4) Else C1.VAL / C2.VAL End ----可以在WHERE里面过滤掉除数为0的情况
When 5 Then C2.VAL - C1.VAL
When 6 Then Case When C1.VAL = 0 Then Power(20, 4) Else C2.VAL / C1.VAl End
End As Decimal(18, 4)) VAL,
OP.PRIO,
C1.MASK + C2.MASK MASK,
C1.USED + C2.USED,
OP.OPER
From POINT C1, OP, CARD12 C2
Where BITAND (C1.MASK, C2.MASK) = 0
--And ------- 既然有MASK, 可以去掉
--(
-- (C1.USED = 2 And C2.USED = 1)
-- Or (C1.USED = 2 And C2.USED = 2)
-- Or (C1.USED = 3 And C2.USED = 1)
--)
And C2.VAL <> Power(20, 4)
And
( -- 尽量去重
OP.ID In (2,4,5,6) -- - /
Or (C1.USED > C2.USED) -- + * 但是操作数不同 --------- 用一个 C1.MASK < C2.MASK 就可以了
Or (C1.USED = C2.USED And C1.MASK < C2.MASK) -- + × 操作数相同,取一边
)
),
POINT24 (EXPR) As
(
Select Distinct EXPR From POINT
Where Abs(VAL - 24) < 0.04 -- 20*20*0.0001 最大可能误差
and MASK = 1 + 2 + 4 + 8
)
Select * From POINT24 Order By EXPR
加了几个注,不明白你为什会那样处理除数为零的情况,另外USED的引入也没有必要。
这个递归的思路我前面也试图使用过,但是递归SQL里面只能引用最近的一层数据,所以写不出N个操作数的通用解法。 |
|