用SQL解决两道有趣的题(一)
上一篇 / 下一篇 2008-01-02 23:45:36 / 个人分类:ORACLE
Oracle的SQL语句功能还是很强的,看到两道比较有趣的题,用SQL来尝试求解。
第一个问题:
已知两个1~30之间的数字,甲知道两数之和,乙知道两数之积。
甲问乙:"你知道是哪两个数吗?"乙说:"不知道";
乙问甲:"你知道是哪两个数吗?"甲说:"也不知道";
于是,乙说:"那我知道了";
随后甲也说:"那我也知道了";
这两个数是什么?
先给出SQL解,然后简单描述一下。
这道题分两种情况,两个数不重复,那么有两个可能结果:
SQL> WITH
4I$e
@#O5Zv
`$Z0 2 T ASITPUB个人空间V^
MAg:R;Q
3 (SELECT ROWNUM NUM FROM DUAL CONNECT BY LEVEL <= 30)ITPUB个人空间F
{+|d0X
K
4 SELECT A, B
G6r8E-k*Fqa)jM0 5 FROMITPUB个人空间q8N3Y&Yrbw
6 (
:W5yd Z8`g1C5N0 7 SELECTITPUB个人空间m3m2q:HHt@9h%}+h
8 A,
O1JhW0kCKC0 9 B,ITPUB个人空间.D
v'g].R*gnq
10 TOTAL,
Vj|,D/J2s7q0 11 MUL,
%oX9eN|lb0 12 COUNT(*) OVER (PARTITION BY MUL) MUL_PITPUB个人空间
h$@j.t4fb
13 FROMITPUB个人空间 DI3y(q1Bi
14 (ITPUB个人空间.r)b5LIM3p*\1{
Z
15 SELECT
iA{ O6sF%l8zy0 16 A,ITPUB个人空间;Bfl-Bf%kUe
17 B,ITPUB个人空间6_Y!qq/tX
18 TOTAL,
Af6Af#Q4R_]0 19 MUL,ITPUB个人空间!JX3E+X(e-Ci{K
20 COUNT(*) OVER (PARTITION BY TOTAL) TOTAL_PITPUB个人空间I7c\-}Gu \b
21 FROMITPUB个人空间+o7Fcn-\
22 (
4I@\*BCe/sG4t$}0 23 SELECTITPUB个人空间&k/oLM h+F[q
24 A.NUM A,ITPUB个人空间#Q.u/J*EL
Id
25 B.NUM B,ITPUB个人空间@0G4i3}9L,m%G
26 A.NUM + B.NUM TOTAL,ITPUB个人空间-HKJX g Z
27 A.NUM * B.NUM MUL,ITPUB个人空间W*M} c.@
|:Qg
28 COUNT(*) OVER (PARTITION BY A.NUM * B.NUM) MUL_PITPUB个人空间
MO(?L q u~+H m]
29 FROM T A, T BITPUB个人空间'eg W(t!n.a;pQ+n[
30 WHERE A.NUM < B.NUM
-@Z"m!Z v;@2WwPp0 31 )ITPUB个人空间6YY2z-t'N:Rh)m6\,W
32 WHERE MUL_P != 1
S$tKB~5r*H?0 33 )ITPUB个人空间3m.{P;aiL!G0P
34 WHERE TOTAL_P != 1
MP$a"b(pHT0 35 )ITPUB个人空间(X0i!n5Q6g+Tj'p"nf!`
36 WHERE MUL_P = 1ITPUB个人空间~}s0sqa4D-L~8v
37 ;
A BITPUB个人空间 X:j
?n0{/r
---------- ----------
m
u%WB8Wb(W6LF!p@0 1 6ITPUB个人空间7y!So2M|/p
1 8
如果两个数是可以重复的,那么有唯一的答案:
SQL> WITH
M
x$e
j&}^`)V0 2 T ASITPUB个人空间X(^8lm3h1}5b
3 (SELECT ROWNUM NUM FROM DUAL CONNECT BY LEVEL <= 30)
(l"b5V&@%q:z0 4 SELECT A, B
;~(n Qd`+kF*l0 5 FROMITPUB个人空间1B{G8iF
6 (ITPUB个人空间7e$db}O+R
Z
7 SELECTITPUB个人空间}6J'?t_0j
Xe
8 A,ITPUB个人空间Y-b(Q"aNg^i#hU"D
9 B,ITPUB个人空间&H+ou_$OB
10 TOTAL,
8F5y0?quw$?5x8S v0 11 MUL,ITPUB个人空间:~n"K)`j []
12 COUNT(*) OVER (PARTITION BY MUL) MUL_PITPUB个人空间)j ]3G.`4w\3R@8N
13 FROM
%b)Q$ss8kXkFQ0 14 (ITPUB个人空间'w2C-Z u
d[
15 SELECTITPUB个人空间9m*y)g(DHx#X(Hb
16 A,ITPUB个人空间9C,KK0N _m@
17 B,ITPUB个人空间:}H2SJ9A1ju:L
18 TOTAL,
I1I"My2^-i,Q0 19 MUL,ITPUB个人空间:G*@M}6M$I!dj&chW-Y
20 COUNT(*) OVER (PARTITION BY TOTAL) TOTAL_P
aqBj
@|Rk0 21 FROM
`.E't8X*v'q|9L{o0 22 (ITPUB个人空间{viyS A
23 SELECT
5]8k6|P$mA'G0 24 A.NUM A,ITPUB个人空间`z.fu
k/F'X
25 B.NUM B,
U/w{
V-s7?a⋘G(X0 26 A.NUM + B.NUM TOTAL,
sh.E]h
u0 27 A.NUM * B.NUM MUL,ITPUB个人空间*g,AkPRE Z$l
28 COUNT(*) OVER (PARTITION BY A.NUM * B.NUM) MUL_PITPUB个人空间$R},\j7L-UW*C'L:F
29 FROM T A, T BITPUB个人空间|3KV5U [J j
30 WHERE A.NUM <= B.NUMITPUB个人空间 Q([e m$G,f
J,Q|6M"W\
31 )
)t+S2t3wW8MVR0 32 WHERE MUL_P != 1ITPUB个人空间ic.LJ L(M,?
33 )ITPUB个人空间A`FD$}/e'P
34 WHERE TOTAL_P != 1
#bN#?GY0 35 )ITPUB个人空间c7g"u KE;B+sd9x,s
36 WHERE MUL_P = 1ITPUB个人空间wn*R m5cJ
c^8LT
37 ;
A B
J6KnAsR0---------- ----------ITPUB个人空间MiE Ypal!C
1 4
下面简单描述一下思路:
WITH语句就是构造一张基础数据表。
最内层的循环构造两个数的笛卡儿积,列出所有的可能,不过对于我们来说,A取1,B取2和A取2,B取1没有区别,因此加上限制条件A > B。上面两个SQL唯一的区别就在这里,如果两个数是可以重复的那么A >= B,否则A > B。
循环中的分析函数用来计算A和B乘积相同的个数,如果这个数是1,说明这两个数是可以确定的。而根据乙的描述,他并不知道这两个数是什么,因此这部分应该是可以被排除的。
第二层的循环道理相同,这里排除的是A所不知道的,两个数和能确定这两个数的部分。
到了第三层,乙知道A和B是什么数了,说明这个时候A和B的积已经是唯一的。
导入论坛 引用链接 收藏 分享给好友 推荐到圈子 管理 举报
TAG: