天天看點

mysql+sql+子查詢語句_SQL語句:子查詢

一,子查詢簡介:

子查詢就是嵌套在主查詢中的查詢。

子查詢可以嵌套在主查詢中所有位置,包括SELECT、FROM、WHERE、ORDER BY。但并不是每個位置嵌套子查詢都是有意義并實用的。

子查詢必須“自身就是一個完整的查詢”。即,它必須至少包括一個SELECT子句和FROM子句。

子查詢的分類:

相關子查詢:

執行依賴于外部查詢的資料。(就是table1在該select外面,而select裡面table1.xx=table2.xx)

外部查詢傳回一行 ,子查詢就執行一次。(對于該select,裡面的子select會重複很多次執行)

非相關子查詢:

獨立于外部查詢的子查詢。

子查詢總共執行一次,執行完畢後後将值傳遞給外部查詢。

二,子查詢的傳回:

一個子查詢會傳回一個标量(單一值)、一個行、一個列或一個表(一行或多行及一列或多列)。這些子查詢被稱為标量、列、行和表子查詢

1,單行單列,聚合(标量):

傳回的結果集為單個的子查詢,叫做單行子查詢。單行比較符有: =、 >、>=、

2,單行多列:

SELECT * FROM t1 WHERE (1,2) = (SELECT column1,column2 FROM t2);

SELECT* FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

如果在表t2的一個行中,column1=1并且column2=2,則查詢結果均為TRUE。

表達式(1,2)和ROW(1,2)有時被稱為行構造符。兩者是等同的,在其它的語境中也是合法的。例如,以下兩個語句在語義上是等同的(但是目前隻有第二個語句可以被優化):

SELECT * FROM t1 WHERE (column1,column2) = (1,1);

SELECT* FROM t1 WHERE column1 = 1 AND column2 = 1;

3,單列:

傳回的結果集為多個的子查詢,為多行子查詢,多行子比較符有 IN(等于列中任意一個)、ANY(和子查詢傳回的某個值比較),ALL(和子查詢傳回的所有值比較)

NOT IN 是 <>ALL 的别名

IN 是 = ANY 的别名

4,多行多列的子表:

可以用在where子句中的 exists,not exists的查詢條件;或者from子句後面(此時子表必須命名,并且不能為有關聯的子查詢)

五,在FROM中嵌套

from下的子查詢 相當于傳回一張表,并且要強制取名。

from子句中的子查詢不能為有關聯的子查詢。

在SELECT語句的FROM子句中,子查詢是合法的。實際的文法是:

SELECT ... FROM (subquery) [AS] name ...

[AS]name子句是強制性的,因為FROM子句中的每個表必須有一個名稱。在子查詢選擇清單中的任何列都必須有唯一的名稱。假設有如下一個表:

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

下面使用了示例表,解釋了在FROM子句中如何使用子查詢:

INSERT INTO t1 VALUES (1,'1',1.0);

INSERT INTO t1 VALUES (2,'2',2.0);

SELECT sb1,sb2,sb3

FROM (SELECT s1AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) ASsb

WHERE sb1> 1;//結果:2, '2', 4.0。

下面是另一個例子:假設您想了解一個分類後的表的一組和的平均值。采用如下操作:

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

不過,本查詢提供所需的資訊:

SELECT AVG(sum_column1)

FROM (SELECT SUM(column1)ASsum_column1

FROM t1 GROUP BY column1)AS t1;

注意,在子查詢中使用的列名稱(sum_column1)被整理到外部查詢中。

六,在SELECT中嵌套:

select中的子查詢如果是相關子查詢,一般可以和join關聯查詢轉換

現有表兩張:一張學生表、一張班表。id相關聯

mysql+sql+子查詢語句_SQL語句:子查詢
mysql+sql+子查詢語句_SQL語句:子查詢

學生資訊和班級名稱位于不同的表中,要在同一張表中查出學生的學号、姓名、班級名稱:

SELECT s.student_id,s.student_name,(SELECT class_name FROM t_class c WHERE c.class_id=s.class_id) FROM t_student s GROUP BY s.student_id;

七,在WHERE中嵌套:

現要查出C語言成績最高的學生的資訊:

SELECT * FROM t_student WHERE student_subject='C語言' AND student_score>=

ALL (SELECT student_score FROM t_student WHERE student_subject='C語言') ;

這裡出現了一個ALL,其為子查詢運算符

分類:

–ALL運算符

和子查詢的結果逐一比較,必須全部滿足時表達式的值才為真。

–ANY運算符

和子查詢的結果逐一比較,其中一條記錄滿足條件則表達式的值就為真。

–EXISTS/NOT EXISTS運算符

EXISTS判斷子查詢是否存在資料,如果存在則表達式為真,反之為假。NOT EXISTS相反。

在子查詢或相關查詢中,要求出某個列的最大值,通常都是用ALL來比較,大意為比其他行都要大的值即為最大值。

要查出C語言成績比李四高的學生的資訊:

SELECT * FROM t_student WHERE student_subject='C語言' AND student_score >

(SELECT student_score FROM t_student WHERE student_name='李四' AND student_subject='C語言');

通過上面兩例,應該可以明白子查詢在WHERE中嵌套的作用。通過子查詢中傳回的列值來作為比較對象,在WHERE中運用不同的比較運算符來對其進行比較,進而得到結果。

現在我們回到最開始的問題,怎麼查出每門課最高成績的學生的資訊:(這個也是相關子查詢)

SELECT * FROM t_student s1 WHERE s1.student_score >=

ALL(SELECT s2.student_score FROM t_student s2 WHERE s1.`student_subject`=s2.student_subject);

這裡就是上文提到的别名的第二種用法,主、子查詢對同一張表操作,區分開位于内外表中相同的列名。

八,order by子查詢

需求舉例:按平均值排序

select 學号,姓名,專業名 from xs where 專業名 = '計算機'

order by (select avg() from xs_kc group by xs_kc.學号 having xs_kc.學号=xs.學号);

三,EXISTS和NOT EXISTS

該文法可以了解為:将主查詢的資料,放到子查詢中做條件驗證,根據驗證結果(TRUE 或 FALSE)來決定主查詢的資料結果是否得以保留。

#exists的例子

SELECT s.Sname FROM student s WHERE EXISTS

(SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname = '信号與系統')

//裡面還用到了from多個表的情況,from多個表的時候按條件笛卡爾積

#not exists的例子

SELECT Sname FROM Student WHERE NOT EXISTS

(SELECT * FROM Course WHERE NOT EXISTS

(SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno) );

四,子查詢和join轉換情況

#使用join

update member set nickname = member_update_store.nickname from member joinmember_update_store

on (member.id=member_update_store.memberid)

where member.id in(1,2,3) and member_update_store.nickname is not null;

#使用子查詢

update member set nickname = (select nickname frommember_update_store

where member_update_store.memberid = member.id and member_update_store.nickname is not null)

where id in(1,2,3);