Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          一段很繞的SQL(雙重否定)
          ?
          ??? 前段時間看到一段SQL,感覺實現的邏輯非常繞,而且看了之后想了很久都沒有想明白到底是怎么回事,再一直想到我都能記住這段SQL的具體細節了,放到博客上研究一下。以下模擬環境:
          ?
          create table t1 (a int,b int);
          insert into t1 values(1,1);
          insert into t1 values(1,2);
          insert into t1 values(1,3);
          insert into t1 values(2,2);
          insert into t1 values(2,3);
          insert into t1 values(4,1);
          insert into t1 values(4,2);
          insert into t1 values(4,3);
          insert into t1 values(5,1);
          insert into t1 values(5,6);
          insert into t1 values(6,1);
          commit;
          ?
          SQL> select * from t1;
          ?
          ??? A???? B
          ----- -----
          ??? 1???? 1
          ??? 1???? 2
          ??? 1???? 3
          ??? 2???? 2
          ??? 2???? 3
          ??? 4???? 1
          ??? 4???? 2
          ??? 4???? 3
          ??? 5???? 1
          ??? 5???? 6
          ??? 6???? 1
          11 rows selected
          ?
          ?
          ??? 問題是這樣的:t1表中A代表人員編號,B代表事件編號。要求出t1表中所有包含人員2所對應的事件的人員編號。
          ??? 它給出的答案是這樣的:
          ?
          select distinct a
          ? from t1 a
          where not exists (select 1
          ????????? from t1 b
          ???????? where a = '2'
          ?????????? and not exists (select 1
          ????????????????? from t1 c
          ???????????????? where c.a = a.a
          ?????????????????? and c.b = b.b));
          ?
          ?
          ??? 首先可以確定的是結果肯定是正確的。然后來看一下邏輯:這段SQL中用了兩層not exists,是用雙重否定來取出最終結果的,但是具體的邏輯始終沒有看明白,到網上搜索了一下,發現遇到這個問題的人還挺多,找了個比較能夠看懂的解答看了下,總算明白了點:
          ?
          http://zhidao.baidu.com/question/47772985.html
          ?
          ?
          ?
          ?
          ??? 關于這道題目可能需要這樣來理解:
          ?
          ??? 1、先看最內層
          ?
          ??? select *
          ????? from t1 b
          ???? where a = '2'
          ?????? and not exists (select 1 from t1 c where c.b = b.b)
          ?
          ??? 這個代表人員2對應的事件中,沒有任何人對應的集合,很顯然是一個空集,因為即便沒有任何人對應,也有人員2自己對應。但是如果在c中加一個人員號的限定條件就不一定存在值了。
          ?
          ??? 2、在最內層中加上a限定
          ?
          ??? select *
          ????? from t1 b
          ???? where a = '2'
          ?????? and not exists (select 1
          ????????????? from t1 c
          ???????????? where c.a = &a
          ?????????????? and c.b = b.b)

          ??? 這就表示人員&a對應的事件中,沒有和人員2對應事件相同的事件集合。所以只要在這個查詢中沒有值的,即表示這個人員對應的事件包含了所有人員2對應的事件。如果有值則表示人員2對應的事件有1件或1件以上是該人員所沒有的。
          ?
          ??? 3、最外層就比較明顯了
          ?
          ??? select distinct a
          ????? from t1 a
          ???? where not exists (select 1
          ????????????? from t1 b
          ???????????? where a = '2'
          ?????????????? and not exists (select 1
          ????????????????????? from t1 c
          ???????????????????? where c.a = a.a
          ?????????????????????? and c.b = b.b))
          ??? 用最外層的a.a代替了&a,即把所有人員都進行比對,凡事在下面不存在值的(剛才判斷過了,不存在值即包含了2對應的所有事件),即需要獲取的人員信息。
          ???
          ?
          posted on 2009-06-12 21:36 decode360 閱讀(2637) 評論(0)  編輯  收藏 所屬分類: 05.SQL
          主站蜘蛛池模板: 双流县| 高州市| 博野县| 西和县| 岢岚县| 金塔县| 日喀则市| 都江堰市| 辽宁省| 称多县| 莲花县| 田东县| 西青区| 东源县| 股票| 老河口市| 普兰县| 玉门市| 桓仁| 扎鲁特旗| 咸宁市| 南江县| 松滋市| 盐亭县| 长武县| 苍溪县| 凭祥市| 高密市| 正定县| 都匀市| 齐河县| 永安市| 建德市| 延川县| 灵璧县| 奇台县| 驻马店市| 太仆寺旗| 织金县| 塘沽区| 邵武市|