1. 程式人生 > >基礎很重要~~04.表表達式-上篇

基礎很重要~~04.表表達式-上篇

 以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL效能優化。

本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。

概述:

本篇主要是對錶表示式中派生表和公用表表達式基礎的總結。

表表達式包含四種:

  1.派生表

  2.公用表表達式

  3.檢視

  4.內聯表值函式

本篇是表表達式的上篇,只會講到派生表和公用表表達式,下篇會講到檢視和內聯表值函式。

下面是表表達式的思維導圖:

 

表表達式:

1.一種命名的查詢表示式,代表一個有效的關係表。

2.可以像其他表一樣,在資料處理語句中使用表表達式。

3.在物理上不是真實存在的什麼物件,它們是虛擬的。對於表示式的查詢在資料庫引擎內部都將轉化為對底層物件的查詢。

為什麼使用表表達式:

1.使用表表達式的好處是邏輯方面,在效能上沒有提升。

2.通過模組化的方法簡化問題的解決方案,規避語言上的某些限制。在外部查詢的任何字句中都可以引用在內部查詢的SELECT字句中分配的列別名。比如在SELECT字句中起的別名,不能在WHERE,group by等字句(邏輯順序位於SELECT字句之前的字句)中使用,通過表表達式可以解決這類問題。

一、派生表

1.用法:

使用地方:外部查詢的FROM字句中定義

存在範圍:外部查詢一結束,派生表就不存在

語法:派生表的查詢語句寫在括號裡面,括號外面跟著AS關鍵字和派生表的名稱。

SELECT columns FROM ( SELECT columns FROM Table ) AS TABLE_1

例子:

SELECT  *
FROM    ( SELECT    orderdate
          FROM      Sales.Orders
          WHERE     orderdate = '20070101'
        ) AS O1

定義了一個O1的派生表,返回所有訂單日期='20070101'的訂單,外部查詢返回派生表的所有行。

在這個例子中,其實不需要派生表,只是為了演示派生表的語法。

注意:

要有效定義任何型別的表表達式,查詢語句必須滿足三個要求:

1)不保證有一定的順序。

表表達式是一個表,而關係表中的行駛沒有固定順序的,所以 ANSI SQL 不允許表表達式查詢語句中出現ORDER BY字句。除非另外還指定了 TOP FOR XML,否則,ORDER BY 子句在檢視、行內函數、派生表、子查詢和公用表表達式中無效。

2)所有的列必須有名稱

3)所有的列必須是唯一的

當表表達式的查詢聯接了兩個表,而這兩個表存在名稱相同的列時,就會出現相同名稱的列,如果要使表示式有效,則必須使這兩個表的列名不一樣。

3.分配列別名

例子:

下面的SQL語句是無效的:

SELECT  YEAR(orderdate) AS orderyear
FROM    Sales.Orders
GROUP BY orderyear 

方案一:SELECT字句和GROUP BY字句中都定義YEAR(orderdate)

SELECT  YEAR(orderdate) AS orderyear
FROM    Sales.Orders
GROUP BY YEAR(orderdate)

方案二:派生表

因為GROUP BY語句的是在SELECT字句之前執行的,所以GROUP BY字句不能引用SELECT字句中定義的別名orderyear

解決辦法是使用表表達式:

SELECT  orderyear
FROM    ( SELECT    YEAR(orderdate) AS orderyear
          FROM      Sales.Orders
        ) AS O1

GROUP BY orderyear

結果:

派生表O1是欄位orderyear的集合,外部查詢SELECT字句和GROUP BY字句可以引用派生表O1orderyear欄位。

SQL SERVER在執行時會擴充套件表表達式的定義,以便直接訪問底層物件。擴充套件後,與方案一類似。

一般來說,表表達式既不會對效能產生正面影響,也不會對效能產生負面影響。

3.使用引數

在派生表的查詢中,可以引用引數。

例子:

基於上面的例子我們定義了一個標量@orderid,在派生表查詢語句中的WHERE字句中引用這個引數。

--定義引數@orderid的值等於,引數型別為INT型別
DECLARE @orderid AS INT = 10248
        
SELECT  orderyear
FROM    ( SELECT            FROM      Sales.Orders
          WHERE orderid = @orderid
        ) AS O1
GROUP BY orderyear

4.巢狀

如果須要用一個本身就引用了某個派生表的查詢去定義另一個派生表,最終得到的就是巢狀派生表。

例子:查詢用於返回訂單年份和該年處理的客戶數,要求每個訂單年份處理的客戶數要多於10

方案一:我們用第一節中單表查詢查詢出結果

SELECT  YEAR(orderdate) AS orderyear ,
        COUNT(DISTINCT custid) AS numcuts
FROM    Sales.Orders
GROUP BY YEAR(orderdate)

HAVING  COUNT(DISTINCT custid) > 10

方案二:巢狀派生表

SELECT  orderyear ,
        numcuts
FROM    ( SELECT    orderyear ,
                    COUNT(DISTINCT custid) AS numcuts
          FROM      ( SELECT    YEAR(orderdate) AS orderyear ,
                                custid
                      FROM      Sales.Orders
                    ) AS O1
          GROUP BY  orderyear
        ) AS O2
WHERE   numcuts > 10

巢狀查詢看起來非常複雜,巢狀查詢也是很容易產生問題的一個方面。在這個例子中,使用巢狀派生表的目的是為了重用列別名。但是,由於巢狀增加了程式碼的複雜性,所以對於本例考慮使用方案一。

5.練習題

1.寫一個查詢,為每個僱員返回其訂單日期最近的所有訂單(用派生表)

期望結果:

本題分兩個步驟:

1.可以先查詢出每個僱員的訂單的最大日期,生成派生表O1

2.O1Sales.Orders表進行關聯,查詢出每個僱員處理過的訂單日期等於最大的訂單日期的所有訂單。

SELECT  O2.empid ,
        O2.orderdate ,
        orderid ,
        custid
FROM    ( SELECT    empid ,
                    MAX(orderdate) AS orderdate
          FROM      Sales.Orders
          GROUP BY  empid
        ) AS O1
        INNER JOIN Sales.Orders AS O2 ON O1.empid = O2.empid
                                         AND O1.orderdate = O2.orderdate

二、公用表表達式

公用表表達式是和派生表相似的另一種形式的表表達式,但是公用表表達式具有一些優勢。

1.語法:

內聯格式:別名寫在內部查詢中

WITH 表名
AS
(
	內部查詢
)
外部查詢
例子: WITH O1 AS ( SELECT custid,companyname FROM Sales.Customers ) SELECT * FROM O1

外聯格式:列的別名寫在外部查詢中

WITH 表名(別名)
AS
(
	內部查詢
)
外部查詢

例子:
WITH O1(custid_1,companyname_1)
AS
(
	SELECT custid,companyname FROM Sales.Customers
)
SELECT * FROM O1

2.用法

公用表表達式和派生表一樣,前面需要遵守的規則對公用表表達式同樣適用。當外部查詢結束,公用表表達式的生命週期就結束了。

3.使用引數

和派生表一樣,可以引用引數。

例子:

DECLARE @custid AS INT = 10248;
 
WITH O1(custid_1,companyname_1)
AS
(
	SELECT custid,companyname FROM Sales.Customers
	WHERE @custid = @custid
)
SELECT * FROM O1

4.定義多個CTE

CTE和派生表相關具有以下優勢:

如果要在一個CTE中引用另一個CTE,不須要像派生表那樣進行巢狀,只需要在同一個WITH字句中定義多個CTE,並用逗號把它們分隔開。每個CTE可以引用在它前面定義的所有CTE,而外部查詢則可以引用所有CTE

如下面的例子,將巢狀派生表改為多個CTE:

WITH C1 AS
(
    SELECT  YEAR(orderdate) AS orderyear ,
            custid
    FROM    Sales.Orders
),
C2 AS
(
    SELECT  orderyear ,
            COUNT(DISTINCT custid) AS numcusts
    FROM    C1
    GROUP BY orderyear
)
SELECT  orderyear ,
        numcusts
FROM    C2

5.練習題

為每個訂單按照orderdateorderid的順序來計算其行號,並返回行號在11~20之間的行。

期望結果:

本題分兩個步驟:

1.查詢出基於orderdateorderid排序的結果集,然後將這個查詢語句用CTE來表示

2.查詢第一步結果集中11~20之間的行

WITH O1
AS
(
	SELECT  orderid ,
			orderdate ,
			custid ,
			empid ,
			ROW_NUMBER() OVER ( ORDER BY orderdate, orderid ) AS rownum
	FROM    Sales.Orders
)    
 
SELECT  *
FROM    O1
WHERE   rownum BETWEEN 11 AND 20

參考資料:

《SQL2008技術內幕:T-SQL語言基礎》


作  者:
出  處:http://www.cnblogs.com/jackson0714/
關於作者:專注於微軟平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!

相關推薦

基礎重要~~04.表表-

 以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL效能優化。 本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。 概述: 本篇主要是對錶表示式中派生表和公用表表達式基礎的總結。 表表達式包含四種:   1.派生表   2.公用表表達式  

基礎重要~~04.表表-下篇

 以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL效能優化。 本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。 概述: 本篇主要是對錶表示式中檢視和內聯表值函式基礎的總結。 表表達式包含四種:   1.派生表   2.公用表表達式   

基礎重要~~04.表表達

cit sca 頭部 生成 res alter 加密 貴的 return 閱讀目錄 概述: 一、視圖 二、內聯表值函數 三、APPLY運算符 以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL性能優化。 本系列【T-SQL基礎】主

SQL Server-表表基礎

sql server表表達式表表達式沒有任何的物理實例化,在查詢表表達式時它們是虛擬的,內部查詢是非嵌套的,換句話說,外部查詢和內部查詢直接合並到一個底層對象的查詢中,使用表表達式的好處通常與代碼的邏輯方面有關,而與代碼的性能無關-摘抄自SQL Server 2012基礎教程。在使用表表達式時我們必須滿足以下

JSTL表表基礎

ring 作用 狀態 value current style 結合 nco The <%@page language="java" pageEncoding="utf-8" import="java.util.*" %> <%@ taglib prefi

公用表表(CTE)

運行 語句 提升 ... 特性 自身 技術分享 欄目 結構   在編寫T-SQL代碼時,往往需要臨時存儲某些結果集。前面我們已經廣泛使用和介紹了兩種臨時存儲結果集的方法:臨時表和表變量。除此之外,還可以使用公用表表達式的方法。公用表表達式(Common Table Expr

sql 異常<除非另外還指定了 TOP、OFFSET 或 FOR XML,否則,ORDER BY 子句在視圖、內聯函數、派生表、子查詢和公用表表中無效。>

select sel top percent 異常 子句 cor 查詢 表達 問題:當子查詢內存在ORDER BY 字句時查詢會報錯 SQL: SELECT * FROM (   SELECT * FROM USER ORDER BY USER_CORD ) S. 解

python 鏈表表 map、filter易讀版

ali required rake 創建鏈表 保留 guid lambda dbo hand 鏈表推導式 [x for x in x] 鏈表推導式提供了一個創建鏈表的簡單途徑,無需使用 map(), filter() 以及 lambda。返回鏈表的定義通常要比

SQL中使用WITH AS提高性能-使用公用表表(CTE)簡化嵌套SQL

column 簡化 expr tor .com 獲取 另一個 rom 指定 一.WITH AS的含義 WITH AS短語,也叫做子查詢部分(subquery factoring),可以讓你做很多事情,定義一個SQL片斷,該SQL片斷會被整個SQL語句所用到。有的時候

HGDB中CTE(公共表表)的用法

目錄 文件用途 詳細資訊 文件用途 本文介紹了HGDB中CTE(公共表表達式)普通用法及遞迴用法。 詳細資訊     Common table expression(公共表表達式)簡稱CTE,由SQL:1999標準引入,CTE可以看成是一個臨時建立的檢視,

SQL Server 公用表表(CTE)實現遞迴

公用表表達式簡介: 公用表表達式 (CTE) 可以認為是在單個 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語句的執行範圍內定義的臨時結果集。CTE 與派生表類似,具體表現在不儲存為物件,並且只在查詢期間有效。與派生表的不同之處在於,公用表表達式 (CTE) 具有一個

針對sql錯誤:“除非另外還指定了 TOP 或 FOR XML,否則,ORDER BY 子句在檢視、行內函數、派生表、子查詢和公用表表中無效”的原理與解決

執行sql語句: select * from ( select * from tab where ID>20 order by userID desc ) as a order by date desc 邏輯上看著挺對 但是報錯: 除非另

使用公用表表(CTE)簡化巢狀SQL 和進行遞迴呼叫

    上圖顯示了一個表中的資料,這個表有三個欄位:id、node_name、parent_id。實際上,這個表中儲存了一個樹型結構,分三層:省、市、區。其中id表示當前省、市或區的id號、node_name表示名稱、parent_id表示節點的父節點的id。    現在有一個需求,要查詢出某個省下面的所有

SQL中使用WITH AS提高效能-使用公用表表(CTE)簡化巢狀SQL

原文:http://wudataoge.blog.163.com/blog/static/80073886200961652022389/一.WITH AS的含義     WITH AS短語,也叫做子查詢部分(subquery factoring),可以讓你做很多事情,定義一

SQL Server2005雜談(3):公用表表(CTE)的遞迴呼叫

 本文為原創,如需轉載,請註明作者和出處,謝謝! 先看如下一個資料表(t_tree):     上圖顯示了一個表中的資料,這個表有三個欄位:id、node_name、parent_id。實際上,這個表

Sql — CTE公用表表和With用法總結

CTE(Common Table Expression) 公用表表達式,它是在單個語句的執行範圍內定義的臨時結果集,只在查詢期間有效。它可以自引用,也可在同一查詢中多次引用,實現了程式碼段的重複利用。 CTE最大的好處是提升T-Sql程式碼的可讀性,可以更加優雅簡潔的方

SQL Server2005雜談(2):公用表表(CTE)的遞迴呼叫

本文為原創,如需轉載,請註明作者和出處,謝謝! 上一篇:SQL Server2005雜談(1):使用公用表表達式(CTE)簡化巢狀SQL 先看如下一個資料表(t_tree):     上圖顯示了一

T-SQL查詢進階--詳解公用表表(CTE)

簡介      對於SELECT查詢語句來說,通常情況下,為了使T-SQL程式碼更加簡潔和可讀,在一個查詢中引用另外的結果集都是通過檢視而不是子查詢來進行分解的.但是,檢視是作為系統物件存在資料庫中,那對於結果集僅僅需要在儲存過程或是使用者自定義函式中使用一次的時候,

SQL Server2005中的公用表表(CTE)的遞迴呼叫

public resultset getResultSet(resultset) { if(resultset is null) { current_resultset =第一個結果集(包含省的記錄集) 將結果集的id儲存在集合中 getResu

除非另外還指定了 TOP 或 FOR XML,否則,ORDER BY 子句在視圖、內聯函數、派生表、子查詢和公用表表中無效

condition 分組 gif 篩選器 使用 外部 如果 代碼 con   SQL 不同於與其他編程語言的最明顯特征是處理代碼的順序。在大數編程語言中,代碼按編碼順序被處理,但是在SQL語言中,第一個被處理的子句是FROM子句,盡管SELECT語句第一個出現,但是幾乎總是