Decode360's Blog

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

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          一段很繞的SQL(雙重否定)
          ?
          ??? 前段時間看到一段SQL,感覺實現(xiàn)的邏輯非常繞,而且看了之后想了很久都沒有想明白到底是怎么回事,再一直想到我都能記住這段SQL的具體細節(jié)了,放到博客上研究一下。以下模擬環(huán)境:
          ?
          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,是用雙重否定來取出最終結果的,但是具體的邏輯始終沒有看明白,到網上搜索了一下,發(fā)現(xiàn)遇到這個問題的人還挺多,找了個比較能夠看懂的解答看了下,總算明白了點:
          ?
          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
          主站蜘蛛池模板: 秦皇岛市| 姚安县| 崇信县| 云阳县| 延吉市| 东海县| 丹东市| 九龙坡区| 甘泉县| 黑山县| 泰顺县| 长白| 安庆市| 石渠县| 永寿县| 杭锦后旗| 大兴区| 连江县| 大渡口区| 平塘县| 雅安市| 蓝田县| 松桃| 霍林郭勒市| 峨边| 翁源县| 三明市| 喀什市| 同德县| 东平县| 莎车县| 澄迈县| 尼勒克县| 河池市| 涡阳县| 隆化县| 凤凰县| 曲麻莱县| 吕梁市| 滨海县| 南部县|