讀SQL進階教程筆記05_關聯子查詢

来源:https://www.cnblogs.com/lying7/archive/2023/04/02/17277869.html
-Advertisement-
Play Games

1. 關聯子查詢 1.1. 關聯子查詢和自連接在很多時候都是等價的 1.2. 使用SQL進行行間比較時,發揮主要作用的技術是關聯子查詢,特別是與自連接相結合的“自關聯子查詢” 1.3. 缺點 1.3.1. 代碼的可讀性不好 1.3.1.1. 特別是在計算累計值和移動平均值的例題里,與聚合一起使用後, ...


1. 關聯子查詢

1.1. 關聯子查詢和自連接在很多時候都是等價的

1.2. 使用SQL進行行間比較時,發揮主要作用的技術是關聯子查詢,特別是與自連接相結合的“自關聯子查詢”

1.3. 缺點

  • 1.3.1. 代碼的可讀性不好

    • 1.3.1.1. 特別是在計算累計值和移動平均值的例題里,與聚合一起使用後,其內部處理過程非常難理解
  • 1.3.2. 性能不好

    • 1.3.2.1. 特別是在SELECT子句里使用標量子查詢時,性能可能會變差

2. 增長、減少、維持現狀

2.1. 使用基於時間序列的表進行時間序列分析

2.2. 示例

  • 2.2.1. --求與上一年營業額一樣的年份(1):使用關聯子查詢
   SELECT year, sale
     FROM Sales S1
    WHERE sale = (SELECT sale
                   FROM Sales S2
                   WHERE S2.year = S1.year -1)
    ORDER BY year;
  • 2.2.2. S2.year = S1.year -1這個條件起到了將要比較的數據偏移一行的作用

  • 2.2.3. --求與上一年營業額一樣的年份(2):使用自連接

   SELECT S1.year, S1.sale
     FROM Sales S1,
         Sales S2
    WHERE S2.sale = S1.sale
     AND S2.year = S1.year -1
    ORDER BY year;

3. 用列表展示與上一年的比較結果

3.1. 示例

  • 3.1.1. --求出是增長了還是減少了,抑或是維持現狀(1):使用關聯子查詢
   SELECT S1.year, S1.sale,
         CASE WHEN sale =
               (SELECT sale
                   FROM Sales S2
                 WHERE S2.year = S1.year -1) THEN'→'--持平
               WHEN sale >
               (SELECT sale
                   FROM Sales S2
                 WHERE S2.year = S1.year -1) THEN'↑'--增長
               WHEN sale <
               (SELECT sale
                   FROM Sales S2
                 WHERE S2.year = S1.year -1) THEN'↓'--減少
         ELSE'—'END AS var
     FROM Sales S1
    ORDER BY year;
  • 3.1.2. --求出是增長了還是減少了,抑或是維持現狀(2):使用自連接查詢(最早的年份不會出現在結果里)
   SELECT S1.year, S1.sale,
         CASE WHEN S1.sale = S2.sale THEN'→'
               WHEN S1.sale > S2.sale THEN'↑'
               WHEN S1.sale < S2.sale THEN'↓'
         ELSE'—'END AS var
     FROM Sales S1, Sales S2
    WHERE S2.year = S1.year -1
    ORDER BY year;

4. 時間軸有間斷時

4.1. 和過去最臨近的時間進行比較

4.2. 示例

  • 4.2.1. --查詢與過去最臨近的年份營業額相同的年份
   SELECT year, sale
     FROM Sales2 S1
    WHERE sale =
     (SELECT sale
         FROM Sales2 S2
       WHERE S2.year =
         (SELECT MAX(year)  --條件2:在滿足條件1的年份中,年份最早的一個
             FROM Sales2 S3
           WHERE S1.year > S3.year))  --條件1:與該年份相比是過去的年份
    ORDER BY year;
  • 4.2.2.  自連接版本
SELECT S1.year AS year,

         S1.year AS year
     FROM Sales2 S1, Sales2 S2
    WHERE S1.sale = S2.sale
     AND S2.year = (SELECT MAX(year)
                       FROM Sales2 S3
                     WHERE S1.year > S3.year)
    ORDER BY year;
  • 4.2.3. --求每一年與過去最臨近的年份之間的營業額之差(1):結果里不包含最早的年份
   SELECT S2.year AS pre_year,
         S1.year AS now_year,
         S2.sale AS pre_sale,
         S1.sale AS now_sale,
         S1.sale - S2.sale  AS diff
     FROM Sales2 S1, Sales2 S2
    WHERE S2.year = (SELECT MAX(year)
                       FROM Sales2 S3
                     WHERE S1.year > S3.year)
    ORDER BY now_year;
  • 4.2.4. --求每一年與過去最臨近的年份之間的營業額之差(1):結果里不包含最早的年份
   SELECT S2.year AS pre_year,
         S1.year AS now_year,
         S2.sale AS pre_sale,
         S1.sale AS now_sale,
         S1.sale - S2.sale  AS diff
     FROM Sales2 S1, Sales2 S2
    WHERE S2.year = (SELECT MAX(year)
                       FROM Sales2 S3
                     WHERE S1.year > S3.year)
    ORDER BY now_year;
  • 4.2.5. 使用極值函數時會發生排序

5. 移動累計值和移動平均值

5.1. 示例

  • 5.1.1. --求累計值:使用視窗函數
   SELECT prc_date, prc_amt,
         SUM(prc_amt) OVER (ORDER BY prc_date) AS onhand_amt
     FROM Accounts;
  • 5.1.2. 引入視窗函數的目的原本就是解決這類問題,因此這裡的代碼非常簡潔

    • 5.1.2.1. 如果選用的資料庫支持視窗函數,也可以考慮使用視窗函數
  • 5.1.3. 從性能方面來看,表的掃描和數據排序也都只進行了一次

    • 5.1.3.1. 依賴於具體的資料庫的
  • 5.1.4. --求累計值:使用馮·諾依曼型遞歸集合

   SELECT prc_date, A1.prc_amt,
         (SELECT SUM(prc_amt)
           FROM Accounts A2
           WHERE A1.prc_date >= A2.prc_date ) AS onhand_amt
     FROM Accounts A1
    ORDER BY prc_date;
  • 5.1.5. --求移動累計值(1):使用視窗函數
   SELECT prc_date, prc_amt,
         SUM(prc_amt) OVER (ORDER BY prc_date
                           ROWS 2 PRECEDING) AS onhand_amt
     FROM Accounts;
  • 5.1.6. --求移動累計值(2):不滿3行的時間區間也輸出
   SELECT prc_date, A1.prc_amt,
         (SELECT SUM(prc_amt)
           FROM Accounts A2
           WHERE A1.prc_date >= A2.prc_date
             AND (SELECT COUNT(*)
                   FROM Accounts A3
                   WHERE A3.prc_date
                     BETWEEN A2.prc_date AND A1.prc_date  ) <= 3 )
                 AS mvg_sum
     FROM Accounts A1
    ORDER BY prc_date;
  • 5.1.7. A3.prc_date在以A2.prc_date為起點,以A1.prc_date為終點的區間內移動

  • 5.1.8. --移動累計值(3):不滿3行的區間按無效處理

   SELECT prc_date, A1.prc_amt,
    (SELECT SUM(prc_amt)
       FROM Accounts A2
     WHERE A1.prc_date >= A2.prc_date
       AND (SELECT COUNT(*)
               FROM Accounts A3
             WHERE A3.prc_date
               BETWEEN A2.prc_date AND A1.prc_date  ) <= 3
     HAVING  COUNT(*) =3) AS mvg_sum  --不滿3行數據的不顯示
     FROM Accounts A1
    ORDER BY prc_date;

5.2. 基本思路是使用馮·諾依曼型遞歸集合

6. 查詢重疊的時間區間

6.1. 示例

  • 6.1.1. --求重疊的住宿期間
   SELECT reserver, start_date, end_date
     FROM Reservations R1
    WHERE EXISTS
         (SELECT *
               FROM Reservations R2
              WHERE R1.reserver <> R2.reserver  --與自己以外的客人進行比較
                AND ( R1.start_date BETWEEN R2.start_date AND R2.end_date
                                   --條件(1):自己的入住日期在他人的住宿期間內
                   OR R1.end_date  BETWEEN R2.start_date AND R2.end_date));
                                   --條件(2):自己的離店日期在他人的住宿期間內
  • 6.1.2. --升級版:把完全包含別人的住宿期間的情況也輸出
   SELECT reserver, start_date, end_date
    FROM Reservations R1
   WHERE EXISTS
         (SELECT *
             FROM Reservations R2
           WHERE R1.reserver <> R2.reserver
             AND (  (     R1.start_date BETWEEN R2.start_date
                                           AND R2.end_date
                       OR R1.end_date   BETWEEN R2.start_date
                                           AND R2.end_date)
                   OR (    R2.start_date BETWEEN R1.start_date
                                           AND R1.end_date
                       AND R2.end_date   BETWEEN R1.start_date
                                           AND R1.end_date)));

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Soda.Http 基於HttpClient封裝的 Http 請求庫。如果有什麼好想法,可以提 Issue 或者 Pr。,如果想要使用,直接在nuget搜索Soda.Http即可。 Github項目地址:Soda.Http 用法 1 預載 預載配置並不是必須的,但是有助於我們進行一些通用基礎設置,例 ...
  • 1. 微軟擴展官網 微軟擴展官網:—>Visual Studio Marketplace 2. 待安裝的擴展包 | 序號 | 擴展包(vsix包) | 官方說明 | | | | | | 1 | ClaudiaIDE | 此擴展更改編輯器的背景圖像 | | 2 | Visual Studio Colo ...
  • ​ 一、前言 在之前的STM32的GPIO理論基礎知識中,分別對基本結構和工作模式進行了詳細的介紹。GPIO基本結構中主要對GPIO內部的各個功能電路逐一的進行的分析;GPIO工作模式中主要介紹GPIO應用在不同的使用場景下,GPIO埠的靜態特征配置和動態的工作模式,同時對信號的工作流進行了分析。 ...
  • 源碼編譯安裝方法 1、上傳包nginx-1.10.0.tar.gz至服務端 # 解壓到工作目錄 [root@template ~]# tar xf nginx-1.10.0.tar.gz -C /usr/local/src/ # 切換至Nginx目錄下,找到configure [root@templ ...
  • rk3399 GPIO的操作方法 RK3399 GPIO分為4個大組 0 ~ 4,每個大組分為4個小組(A,B,C,D),比如GPIO0 有 A,B,C,D四個小組,每個小組有A0~A7個gpio 一個GPIO需要三類功能支持:gpio時鐘,gpio輸入輸出,這個pin要設置為gpio功能(復用) ...
  • 物聯網技術基礎及應用緒論 任課教師:北京化工大學 畢超 課程鏈接:https://www.bilibili.com/video/BV1ha411g7H2/?spm_id_from=333.999.0.0&vd_source=e66dd25b0246f28e772d75f11c80f03c 課程版本: ...
  • 1. SQL的弱點 1.1. SQL語句的執行結果轉換為想要的格式 1.1.1. 格式轉換 1.1.2. SQL語言本來就不是為了這個目的而出現的 1.1.3. SQL終究也只是主要用於查詢數據的語言而已 1.2. 生成報表的功能 1.2.1. 視窗函數 1.3. SQL不是用來生成報表的語言,所以 ...
  • 在docker中配置Oracle11g docker鏡像拉取及相關配置 1.在docker打開的情況下,使用下方命令拉去鏡像,大概需要下載3個G的image文件 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 2.啟動 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...