1. 程式人生 > >SQL Server學習筆記-連接

SQL Server學習筆記-連接

list offer 內連接 rst resource employ sco tab ssi

第四章-連接

內部連接

  • 語法結構

    SELECT <select list>
    FROM <first_table>
    <join_type> <second_table>
      [ON <join_condition>]
  • 使用範例

    SELECT Person.BusinessEntity.*
      FROM Person.BusinessEntity
      INNER JOIN HumanResources.Employee
          ON Person.BusinessEntity.BusinessEntityID = 
          HumanResources.Employee.BusinessEntityID;
  • 內連接具有排他特性.

  • INNER JOIN類似於WHERE

外連接

  • 外連接的簡易語法

    SELECT <SELECT list>
      FROM <the table you want to be the "LEFT" table>
      <LEFT|RIGHT> [OUTER] JOIN <table you want to be the "RIGHT" table>
      ON <join condition>
  • 外連接本質上是包含的.

  • 假設要知道具體折扣信息, 每一種折扣的數量和哪些商品打折.

    SELECT sso.SpecialOfferID, Description, DiscountPct, ProductID
      FROM Sales.SpecialOffer sso
      LEFT JOIN Sales.SpecialOfferProduct ssop
          ON sso.SpecialOfferID = ssop.SpecialOfferID
      WHERE sso.SpecialOfferID != 1;
  • LEFT JOIN保留的是左側表的字段, 如果右側表中不存在與左側表匹配的字段, SQL Server會為其他任意值填充NULL.

  • RIGHT JOIN保留的是右側表的字段, 如果左側表中不存在與右側表匹配的字段, SQL Server會為其他任意值填充NULL.

    SELECT sso.SpecialOfferID, Description, DiscountPct, ProductID
      FROM Sales.SpecialOffer sso
      LEFT JOIN Sales.SpecialOfferProduct ssop
          ON sso.SpecialOfferID = ssop.SpecialOfferID
      WHERE sso.SpecialOfferID != 1;
    
    SELECT sso.SpecialOfferID, Description, DiscountPct, ProductID
      FROM Sales.SpecialOfferProduct ssop
      RIGHT JOIN Sales.SpecialOffer sso
          ON ssop.SpecialOfferID = sso.SpecialOfferID
      WHERE sso.SpecialOfferID != 1;
  • 返回與任何產品不關聯的折扣名稱

    SELECT Description
      FROM Sales.SpecialOffer sso
      LEFT JOIN Sales.SpecialOfferProduct ssop
          ON sso.SpecialOfferID = ssop.SpecialOfferID
      WHERE sso.SpecialOfferID != 1
      AND ssop.SpecialOfferID IS NULL;
    
    SELECT Description
      FROM Sales.SpecialOfferProduct ssop
      RIGHT JOIN Sales.SpecialOffer sso
          ON ssop.SpecialOfferID = sso.SpecialOfferID
      WHERE sso.SpecialOfferID != 1
      AND ssop.SpecialOfferID IS NULL;
  • NULL值不等於NULL值.

    IF (NULL = NULL)
      PRINT ‘It Does‘
    ELSE
      PRINT ‘It Doesn‘‘t‘

處理更復雜的外部連接

-- 返回所有供應商的地址
SELECT v.VendorName, a.Address
    FROM Vendors v
    LEFT JOIN VendorAddress va
        ON v.VendorID = va.VendorID
    LEFT JOIN Address a
        ON va.AddressID = a.AddressID;

SELECT v.VendorName, a.Address
    FROM VendorAddress va
    JOIN Address a
        ON va.AddressID = a.AddressID
    RIGHT JOIN Vendors v
        ON v.VendorID = va.VendorID;

-- 使用分組連接
SELECT v.VendorName, a.Address
    FROM Vendors v
    LEFT JOIN (
        VendorAddress va
        JOIN Address a
        ON va.AddressID = a.AddressID
    )
    ON v.VendorID = va.VendorID;

完全連接

  • FULL JOIN將左右兩側的數據全部匹配, 並返回所有的記錄. 無論記錄在JOIN的哪一側.

  • FULL JOIN查詢出來是兩個表的並集.

    SELECT a.Address, va.AddressID, v.VendorID, v.VendorName
      FROM VendorAddress va
      FULL JOIN Address a
          ON va.AddressID = a.AddressID
      FULL JOIN Vendors v
          ON va.VendorID = v.VendorID;

交叉連接

  • 交叉連接是將JOIN左側的所有記錄與另一側的所有記錄連接.

  • 交叉連接返回的是JOIN兩側表的所有記錄的笛卡爾積.

  • 交叉連接使用範例

    SELECT v.VendorName, a.Address
      FROM Vendors v
      CROSS JOIN Address a;

聯合

  • JOIN 將信息水平連接(添加更多列)

  • UNION 將數據垂直連接(添加更多行)

  • UNOIN查詢的關鍵點

    • 所有聯合的查詢必須在SELECT列表中有相同的列數.
    • UNION返回的結果集的標題(列名)僅從第一個查詢獲得.
    • 查詢中的對應列的數據類型必須隱式一致.
    • UNION查詢的默認返回選項為DISTINCT, 而不是ALL.
  • UNION使用範例:

    SELECT FirstName + ‘ ‘ + LastName AS Name
      FROM Person.Person pp
      JOIN Person.EmailAddress pe
          ON pp.BusinessEntityID = pe.BusinessEntityID
      JOIN Sales.Customer sc
          ON pp.BusinessEntityID = sc.CustomerID
    
      UNION
    SELECT FirstName + ‘ ‘ + LastName AS Name
      FROM Person.Person pp
      JOIN Person.EmailAddress pe
          ON pp.BusinessEntityID = pe.BusinessEntityID
      JOIN Purchasing.Vendor pv
          ON pp.BusinessEntityID = pv.BusinessEntityID
  • UNION去除重復行, SQL Server會將具有相等NULL列的行視為重復行.

    -- 查詢添加特價供應產品的名稱
    SELECT P.ProductNumber, ‘Less than 100 left‘ AS SpecialOffer
      FROM Production.Product P
      JOIN Production.ProductInventory I
          ON I.ProductID = P.ProductID
      WHERE I.Quantity < 100
      UNION
    SELECT P.ProductNumber, SO.Description
      FROM Production.Product P
      JOIN Sales.SpecialOfferProduct O
          ON P.ProductID = O.ProductID
      JOIN Sales.SpecialOffer SO
          ON SO.SpecialOfferID = O.SpecialOfferID
      WHERE O.SpecialOfferID > 1

小結

  • 要排除不匹配的字段的時候 使用內部鏈接(INNER JOIN | JOIN)
  • 要檢索盡可能匹配的數據, 但又要包含JOIN一側的表的所有數據, 使用外部鏈接.(LEFT | RIGHT OUTER JOIN)
  • 要檢索盡可能匹配的數據, 但又要包含JOIN兩側的表的所有數據, 使用完全外連接.(FULL OUTER JOIN)
  • 要基於兩個表的記錄建立笛卡爾積時, 使用交叉連接.(CROSS JOIN)
  • 要將第二個查詢結果附加到第一個查詢結果時, 使用聯合.(UNION | UNION ALL)

練習題

  • 針對AdventureWorks數據庫編寫一條查詢語句, 要求返回Name列並包含NationalIDNumber為112457891的雇員的姓.

    SELECT P.LastName AS Name
      FROM Person.Person P
      JOIN HumanResources.Employee E
          ON P.BusinessEntityID = E.BusinessEntityID
      WHERE E.NationalIDNumber = ‘112457891‘;
  • 針對AdventureWorks數據庫編寫一條查詢語句, 要求返回所有產品的ID和Name列, 包括沒有特價供應的所有產品和有No Discount特價供應的所有產品.

    SELECT P.ProductID, P.Name
      FROM Production.Product P
      LEFT JOIN Sales.SpecialOfferProduct SSP
          ON P.ProductID = SSP.ProductID
      WHERE SSP.SpecialOfferID IS NULL
      UNION
    SELECT P.ProductID, P.Name
      FROM Production.Product P
      JOIN Sales.SpecialOfferProduct SSP
          ON P.ProductID = SSP.ProductID
      JOIN Sales.SpecialOffer SSO
          ON SSO.SpecialOfferID = SSP.SpecialOfferID
      WHERE SSO.Description = ‘No Discount‘;

SQL Server學習筆記-連接