我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

用SQL解决两道有趣的题(一)

上一篇 / 下一篇  2008-01-02 23:45:36 / 个人分类:ORACLE

OracleSQL语句功能还是很强的,看到两道比较有趣的题,用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个人空间 D I3y(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个人空间+o7F cn-\
 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个人空间-HK JXgZ
 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!Zv;@2Ww Pp0 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"n f!`
 36  WHERE MUL_P = 1ITPUB个人空间~}s0s qa4D-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 Q d`+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$?5x8Sv0 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个人空间{v iyS 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&Ll;G(X0 26      A.NUM + B.NUM TOTAL,
sh.E]h u0 27      A.NUM * B.NUM MUL,ITPUB个人空间*g,AkPREZ$l
 28      COUNT(*) OVER (PARTITION BY A.NUM * B.NUM) MUL_PITPUB个人空间$R},\j7L-U W*C'L:F
 29     FROM T A, T BITPUB个人空间|3KV5U [Jj
 30     WHERE A.NUM <= B.NUMITPUB个人空间Q([e m$G,f J,Q|6M"W\
 31    )
)t+S2t3wW8MVR0 32    WHERE MUL_P != 1ITPUB个人空间ic.LJL(M,?
 33   )ITPUB个人空间A` FD$}/e'P
 34   WHERE TOTAL_P != 1
#bN#? GY0 35  )ITPUB个人空间c7g"uKE;B+s d9x,s
 36  WHERE MUL_P = 1ITPUB个人空间wn*Rm5cJ c^8LT
 37  ;

         A          B
J6KnAsR0---------- ----------ITPUB个人空间Mi EYpal!C
         1          4

下面简单描述一下思路:

WITH语句就是构造一张基础数据表。

最内层的循环构造两个数的笛卡儿积,列出所有的可能,不过对于我们来说,A1B2A2B1没有区别,因此加上限制条件A > B。上面两个SQL唯一的区别就在这里,如果两个数是可以重复的那么A >= B,否则A > B

循环中的分析函数用来计算AB乘积相同的个数,如果这个数是1,说明这两个数是可以确定的。而根据乙的描述,他并不知道这两个数是什么,因此这部分应该是可以被排除的。

第二层的循环道理相同,这里排除的是A所不知道的,两个数和能确定这两个数的部分。

到了第三层,乙知道AB是什么数了,说明这个时候AB的积已经是唯一的。

 


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar