1. 程式人生 > >SQL 雙層 not exist 巢狀

SQL 雙層 not exist 巢狀

很早的一個問題了,今天碰到又繞了一下。其實很簡單。

關係模式:
學生(學號,姓名,系別,年齡)
課程(課程號,課程名,學時)
選讀(學號,課程號,成績)
問題:檢索選讀全部課程的學生姓名
select 學生.姓名 from 學生
where not exists(
select * from 課程 where not exists(
select * from 選讀 where 學號=學生.學號 and 課程號=課程.課程號))

意思是
con1:這個學生不會con2。
con2:他有課沒選。

下面是網上關於這件事的討論,弄個合集防止腦子再發懵。。。
現在我們從後面的子查詢向前分解:

1.所有未選過的課程的資料集:
select * from 課程 where not exists(
select * from 選讀 where 課程號=課程.課程號)

2.所有沒被某位學號為 @學號 的學生選過的課程的記錄集(@學號學生的未選課程):
select * from 課程 where not exists(
select * from 選讀 where 學號
[email protected]
學號 and 課程號=課程.課程號)
請注意,多出了學號的篩選即,學號[email protected]學號。

3.遍歷每一個主查詢的學號,每一個學號都按第二篩選方法篩選出:沒有未選課程的學生的學號。(不包括在第查詢方法查詢出的“有未學課程的學號的記錄集”中的記錄。)
請注意:用主查詢中的 學生.學號 代替了@學號。
select 學生.姓名 from 學生
where not exists(
select * from 課程 where not exists(
select * from 選讀 where 學號=學生.學號 and 課程號=課程.課程號))

這已經是整個查詢語句,可以看出子查詢中用學生.學號替換了第2步中的 @學號,(沒忘了吧,第二步求的是沒有選修全部課程的某個學生)。

用上面的講解方法不知道是不是更好理解一點。

===============

針對您最後的補充:

為什麼不用
from 學生,課程,選讀?

答:因為from 學生,課程,選讀 也就是
SELECT * FROM 學生,課程,選讀 WHERE .....條件
這樣的型式只能組成內聯接,而內聯接我們只知道,只有三個表按聯接條件都符合才會被選中,而我們要的是有不符合後面兩表的的學生才符合條件,所以用內聯接是不可行的。

要不然where句怎麼可以呼叫三個關係的屬性呢?

答:在SQL SERVER中規定:所有子表都是可以通過表名呼叫其上面任意層次的表中的欄位的。所以,不是隻有內聯接才可以呼叫多個表的屬性。




雙重否定
從最裡面開始執行

select * from 課程 where not exists(
select * from 選讀 where 學號=學生.學號 and 課程號=課程.課程號))
這段是返回某學生沒有選擇的課程,假設返回集a

前面套個not exists的後,
當a有值,即,某學生存在沒有選擇的課程時,整段sql文返回null,




在這裡http://www.blogjava.net/decode360/archive/2009/06/12/282804.html也有解釋。
當a無值,即,某學生不存在沒有選擇的課程時,就是說選擇了全部課程,整段sql文該學生返回姓名

相關推薦

SQL 雙層 not exist

很早的一個問題了,今天碰到又繞了一下。其實很簡單。 關係模式: 學生(學號,姓名,系別,年齡) 課程(課程號,課程名,學時) 選讀(學號,課程號,成績) 問題:檢索選讀全部課程的學生姓名 select 學生.姓名 from 學生 where not exists( selec

SQL語言中if

再sql語言中,if是沒有大括號的,如下這樣; if  {   ...... if  {          ...... } } else { ...... } 在sql語句中,這樣是不存在的,大括

SQL筆記--遊標/遊標

注意點: 1. While..Bgein之間不可以寫要執行的程式碼,否則會一直執行等待。要放在Begin..End內部。 2. IF ( @@error > 0 )事務執行錯誤判斷放在Begin…End語句塊中,因為Begin是Be

java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist

mysq mysql com 權限 pri png 問題 mage The 權限問題,授權給 root 所有sql 權限 在Navicat for MySQL中按F6進入命令列界面 mysql> grant all privileges on *.* to roo

SQL server中單引號的使用--單引號裡面一層單引號

           在使用SQL server時,遇到一個小問題:單引號裡面還要再加單引號,但是直接加會報錯。查了一些網上的解決方法。     select * from sysobjects where

sql server中事務*

轉自 https://www.cnblogs.com/guanjie20/archive/2013/02/17/2914488.html 我們在寫事務時經常遇到的問題如下: 訊息 266,級別 16,狀態 2,過程 sp1,第 0 行 EXECUTE 後的事務計數指示&nb

SQL語句中not in 和not exist的區別

in和exists in 是把外表和內表作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的。 如果查詢的兩個表大小相當,那麼用in和exists差別不大。 如果兩個表中一個較小,一個是

sql查詢再進行連線

SELECT * from ( SELECT * from tit_training_program WHERE level_id=#{levelId}) as p LEFT JOIN( se

TabLayout + ViewPager輪播圖 (雙層),側拉展示條目(頭像加listview,點選頭像可切換)PullToRefreshListView重新整理載入

模組簡介: 1.底部:TabLayout + ViewPager輪播圖 2.主頁面可測拉 展示頭像,可選擇系統相簿,切換圖片(二級取樣) 3.TabLayout + ViewPager巢狀TabLayout + ViewPager以展示 正在上映 和 *

使用for迴圈雙層 控制檯列印九九乘法表

for(int i = 1;i<=9;i++) { for(int j = 1;j<=9;j++) { System.out.print(i+”*”+j+”=”+i*j+“ ”); } System.out.println(); } for迴圈的執行順序是先完

PL/SQL集合(table)表操作例項講解例項

集合是一個有序組具有相同的資料型別的元素。每個元素進行標識的唯一標表示其在集合中的位置。PL/SQL提供了三種集合型別:索引表或關聯陣列、巢狀表、可變大小的陣列或變長陣列Oracle文件提供了每種型別的集合的以下特徵:集合型別元素數量下標型別密集或稀疏在哪裡建立可以是物件型別

sql語句中2層迴圈

declare @year intdeclare @month intset @year=2008while(@year<=2011)beginset @month=1while(@month<=12)begininsert into tableName values(@year,@month)s

SQL 查詢 建立約束

------------------------巢狀查詢------------------------ use student select * from dbo.stu   ----not in where StudentName not in (select Stude

SQL中的連線查詢與查詢

連線查詢 若一個查詢同時涉及兩個或兩個以上的表,則稱之為連線查詢。連線查詢是資料庫中最最要的查詢, 包括: 1、等值連線查詢 2、自然連線查詢 3、非等值連線查詢 4、自身連線查詢 5、外連線查詢 6、複合條件查詢 等值與非等值連線查詢: 比較運算子主要有=、>、

for迴圈雙層

for迴圈的雙層巢狀只要分為兩種型別:內外巢狀獨立、內外巢狀相關。1、內外巢狀獨立:for(int i=0;i<4;i++) {for(int j=0;j<4;j++) {System.out.print("*");  //注意不是println。print將迴圈

PL/SQL迴圈操作例項

PL/SQL允許使用一個迴圈內巢狀另一個迴圈。在PL/SQL巢狀基本LOOP語句的語法如下: LOOP Sequence of statements1 LOOP Sequence

sql查詢,把一次查詢的結果做為表繼續進一步查詢;內聯檢視

Mysql的巢狀表查詢   巢狀SELECT語句也叫子查詢,一個 SELECT 語句的查詢結果能夠作為另一個語句的輸入值。子查詢可以: 出現在Where子句中, 出現在from子句中,作為一個臨時表使用, 出現在select list中,作為一個欄位值來返回。 示例 1、出現在whe

jdbc對於模糊查詢like語句變數的sql語句寫法

在java寫對資料庫操作的程式時,有時會遇到模糊查詢字串匹配sql語句,這時應該怎麼巢狀變數呢,如下: String sql="select * from admin where name like

SQL語句時的執行順序

1.原語句:SELECT ID,NAME,STATES,(SELECT STATES FROM ITEM  WHERE ID=T.ITEM_ID) AS ITEM_END_FLAGFROM RESULT TWHERE 1=12.ITEM表中實際沒有STATES列,但執行時語句

{dede:sql}標籤中,取出欄位後,對欄位進行邏輯操作時的方法

<div>{dede:sql sql='select body from dede_addonarticle where typeid=4 order by rand() LIMIT 1'} [field:body runphp='yes']