大家應(yīng)該還記得前幾天我們的一篇文章:用SQL解一道有趣的數(shù)學(xué)題:Gauss和Poincare ,,錯過的朋友請先回顧,。感謝網(wǎng)友的反饋,發(fā)來新的解法一則。 如網(wǎng)友所言:這個解法并沒有顛覆性原解法,,只是在一些數(shù)學(xué)邏輯上稍微有些不同,,體現(xiàn)在SQL建模上的少許不同。 這是一個流傳已久的故事: Gauss和Poincare在天堂相遇了,,上帝說:你們都是人間最偉大的數(shù)學(xué)家,,那我來出道題考考你們誰更聰明。我在左手寫一個大于1小于100的數(shù),,在右手同樣寫一個大于1小于100的數(shù),,然后把他們的和寫在Gauss手上,把積寫在Poincare手上,,看看你們能不能猜出這兩個數(shù)字是幾,。
Gauss看了手上的數(shù)字,說:“我不知道這兩個數(shù)字是幾,,可我保證Poincare也不知道,。” Poincare看了手上的數(shù)字,,說:“我原來的確不知道那兩個數(shù)字是幾,,可我現(xiàn)在知道了?!?/span> Gauss說:“那我也知道了,。” 問題:那兩個數(shù)字是幾,? 先看SQL邏輯和結(jié)果: SQL> WITH T_NUM AS 2 (SELECT ROWNUM + 1 NUM FROM DUAL CONNECT BY LEVEL < 99) 3 SELECT A, B 4 FROM 5 ( 6 SELECT A, B,TOTAL,MUL,MUL_M, 7 COUNT(DECODE(MUL_M, 1, 1)) OVER (PARTITION BY TOTAL) MUL_N 8 FROM 9 ( 10 SELECT A, B,TOTAL,MUL,MUL_M 11 FROM 12 ( 13 SELECT 14 A, 15 B, 16 MUL, 17 TOTAL, 18 COUNT(TOTAL) OVER (PARTITION BY MUL) MUL_M 19 FROM 20 ( 21 SELECT 22 A, 23 B, 24 A + B TOTAL, 25 A * B MUL 26 FROM 27 (SELECT A.NUM A, 28 B.NUM B 29 FROM T_NUM A, T_NUM B 30 WHERE A.NUM+B.NUM-2 in( 31 SELECT NUM 32 FROM 33 ( 34 SELECT A.NUM * B.NUM NUM FROM T_NUM A, T_NUM B 35 WHERE A.NUM <= B.NUM 36 AND A.NUM > 1 37 AND B.NUM > 1 38 ) 39 WHERE MOD(NUM,2)=1 AND NUM < 99 40 ) 41 AND A.NUM < B.NUM 42 ) 43 ) 44 ) 45 WHERE MUL_M=1 46 ) 47 ) 48 WHERE MUL_N = 1; A B ---------- ---------- 4 13
剖析說明如下: 高斯知道兩數(shù)之和,,不知道兩數(shù)之積,但卻可以肯定的說龐加萊不知道兩數(shù)是什么,。這說明兩數(shù)之和決定了其對應(yīng)的兩數(shù)之積不可能分解為兩個素因子,。而根據(jù)哥德巴赫猜想(沒錯,就是陳景潤做出了至今最好成績中國人耳熟人詳?shù)哪莻€猜想):任一大于2的偶數(shù)都可以寫成兩個素數(shù)之和,。
這也就是說高斯看到的那個兩數(shù)之和肯定不是偶數(shù),,一定是一個奇數(shù)。而一個奇數(shù)要寫成兩個素數(shù)的和,,一定要包含2這個最小的素數(shù),,所以兩數(shù)之和只要是2+奇合數(shù)的形式就一定不能表示成兩個素數(shù)之和的形式。 分析下最內(nèi)層的SQL: 21 SELECT 22 A, 23 B, 24 A + B TOTAL, 25 A * B MUL 26 FROM 27 (SELECT A.NUM A, 28 B.NUM B 29 FROM T_NUM A, T_NUM B 30 WHERE A.NUM+B.NUM-2 in( 31 SELECT NUM 32 FROM 33 ( 34 SELECT A.NUM * B.NUM NUM FROM T_NUM A, T_NUM B 35 WHERE A.NUM <= B.NUM 36 AND A.NUM > 1 37 AND B.NUM > 1 38 ) 39 WHERE MOD(NUM,2)=1 AND NUM < 99 40 ) 41 AND A.NUM < B.NUM 42 )
這一層的意思是構(gòu)造出所有的兩數(shù)之和減2的結(jié)果是奇數(shù)且是合數(shù)的所有可能性。到了這一步,,高斯看到的兩數(shù)之和就可以肯定的說,,龐加萊一定不知道這兩個數(shù)是什么。 接下來的一步,,實現(xiàn)龐加萊知道了兩個數(shù)是什么,。 10 SELECT A, B,TOTAL,MUL,MUL_M 11 FROM 12 ( 13 SELECT 14 A, 15 B, 16 MUL, 17 TOTAL, 18 COUNT(TOTAL) OVER (PARTITION BY MUL) MUL_M 19 FROM 20 ( 21 SELECT 22 A, 23 B, 24 A + B TOTAL, 25 A * B MUL 26 FROM 27 (SELECT A.NUM A, 28 B.NUM B 29 FROM T_NUM A, T_NUM B 30 WHERE A.NUM+B.NUM-2 in( 31 SELECT NUM 32 FROM 33 ( 34 SELECT A.NUM * B.NUM NUM FROM T_NUM A, T_NUM B 35 WHERE A.NUM <= B.NUM 36 AND A.NUM > 1 37 AND B.NUM > 1 38 ) 39 WHERE MOD(NUM,2)=1 AND NUM < 99 40 ) 41 AND A.NUM < B.NUM 42 ) 43 ) 44 ) 45 WHERE MUL_M=1
這一步根據(jù)兩數(shù)之積分組后的兩數(shù)之和只有一種可能性的,也就是MUL_M=1,,于是龐加萊就知道了,,這兩個數(shù)是什么。 最后一步,,在上一步兩數(shù)之積只有一種可能性的情況下,,兩數(shù)之和只有一種可能性的,也就是MUL_N=1,,于是高斯也知道了這兩個數(shù)是什么,。 注意這個結(jié)果是正確的,思路也非常巧妙,。于是楊長老忍不住技癢,,再次操刀,就有了以下的改變,。 楊長老評價:能利用數(shù)學(xué)知識和算法來進行解題非常難得,。
提幾個小的問題: 1.在構(gòu)造數(shù)組的時候已經(jīng)排除了A和B等于1的情況
WITH T_NUM AS (SELECT ROWNUM + 1 NUM FROM DUAL CONNECT BY LEVEL < 99) 因此36行和37行的判斷不需要: AND A.NUM > 1 AND B.NUM > 1 2.通過數(shù)學(xué)算法可以過濾掉一部分?jǐn)?shù)據(jù),可惜SQL上實現(xiàn)過濾的方法比較復(fù)雜,,反而造成了更多的嵌套,,單次執(zhí)行邏輯讀接近5000,根據(jù)樓主的含義進行了一下改寫,,邏輯讀可以降到230左右: WITH T_NUM AS (SELECT ROWNUM + 1 NUM FROM DUAL CONNECT BY LEVEL < 99), T_ALL AS (SELECT A.NUM A, B.NUM B, A.NUM + B.NUM TOTAL, A.NUM * B.NUM MUL FROM T_NUM A, T_NUM B WHERE A.NUM <= B.NUM) SELECT A, B FROM ( SELECT A, B,TOTAL,MUL,MUL_M, COUNT(DECODE(MUL_M, 1, 1)) OVER (PARTITION BY TOTAL) MUL_N FROM ( SELECT A, B,TOTAL,MUL,MUL_M FROM ( SELECT A, B, MUL, TOTAL, COUNT(TOTAL) OVER (PARTITION BY MUL) MUL_M FROM ( SELECT * FROM T_ALL WHERE A != B AND TOTAL - 2 IN ( SELECT MUL FROM T_ALL WHERE MOD(A, 2) = 1 AND MOD(B, 2) = 1 AND MUL < 99 ) ) ) WHERE MUL_M=1 ) ) WHERE MUL_N = 1;
不僅要實現(xiàn)功能,,還是關(guān)注性能,這是SQL開發(fā)的精髓所在,。 大家可以體驗一下楊長老的強大底蘊和功力,,而云和恩墨SQL審核產(chǎn)品和服務(wù)正是致力于提升SQL性能,改善用戶體驗,。 如果你有更好的解答,,并且對SQL感興趣,請給我一份簡歷:[email protected] .
|