深入解析SQL Server高級SQL技巧

????????SQL Server 是一種功能強大的關系型數據庫管理系統,廣泛應用于各種數據驅動的應用程序中。在開發過程中,掌握一些高級SQL技巧,不僅能提高查詢性能,還能優化開發效率。這篇文章將全面深入地探討SQL Server中的一些高級技巧,并結合實際例子,探索這些技巧在實際的應用。

一、使用CTE(公共表表達式)簡化復雜查詢

什么是CTE?

公共表表達式(CTE,Common Table Expression)是SQL Server的一種查詢功能,它允許臨時定義一個結果集,在查詢的后續部分引用這個結果集。通過使用CTE,我們可以編寫更簡潔、更易于維護的SQL查詢。

CTE的基本語法

WITH CTE_Name AS( SELECT column1, column2, ... FROM table_name WHERE condition ) 
SELECT * FROM CTE_Name;

例子

假設有一張員工表Employees,我們需要查詢每個部門的最高薪資員工:

WITH Department_MaxSalaryAS ( SELECT DepartmentID, MAX(Salary) AS MaxSalary FROM Employees GROUP BY DepartmentID ) 
SELECT E.EmployeeName, E.DepartmentID, E.Salary 
FROM Employees E JOIN Department_MaxSalary DMS 
ON E.DepartmentID = DMS.DepartmentIDAND E.Salary = DMS.MaxSalary;

優勢

  • 使查詢結構更清晰,尤其在需要多次引用某個復雜查詢結果時。
  • 遞歸查詢:CTE支持遞歸操作,適合層級結構數據(如樹狀結構)查詢。

注意

  • CTE僅在當前查詢的生命周期內有效,因此它不會影響全局的查詢性能或結構。

二、窗口函數(Window Functions)

什么是窗口函數?

窗口函數允許我們在結果集中對某些行進行操作,而不必在查詢中重新分組。常見的窗口函數包括ROW_NUMBER()RANK()DENSE_RANK()NTILE()SUM()等。

窗口函數的基本語法

SELECT column1, column2, WINDOW_FUNCTION() OVER (PARTITION BY column ORDER BY column) AS WindowFunctionResult FROM table_name;

例子:使用ROW_NUMBER()為每個部門的員工排名

SELECT EmployeeName, DepartmentID, Salary, ROW_NUMBER()OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS Rank FROM Employees;

在這個例子中,ROW_NUMBER()為每個部門的員工按薪資排名,PARTITION BY用于指定分區,ORDER BY用于確定排序規則。

優勢

  • 不需要子查詢或復雜的連接,簡化查詢結構。
  • 可以執行復雜的排名、累計、移動平均等操作。

注意

  • 窗口函數的執行順序是按OVER子句中的PARTITION BYORDER BY排序的,因此理解它們的使用方式非常重要。

三、使用MERGE語句進行數據同步

什么是MERGE

MERGE語句用于將兩個表的數據進行比較,并在匹配的情況下更新數據,在不匹配的情況下插入或刪除數據。它是處理增量數據同步的一個有效工具。

MERGE的基本語法

MERGE INTO target_table AS target USING source_table AS source ON target.column = source.column WHEN MATCHED THEN UPDATE SET target.column1 = source.column1 WHEN NOT MATCHED BY TARGET THEN INSERT (column1, column2) VALUES (source.column1, source.column2) WHEN NOT MATCHED BY SOURCE THEN DELETE;

例子:將SourceData表的數據同步到TargetData

MERGE INTO TargetData AS target USING SourceDataAS source ON target.ID = source.ID WHEN MATCHED 
THEN UPDATE SET target.Name = source.Name, target.Age = source.Age
WHEN NOT MATCHED BY        
TARGET THEN INSERT (ID, Name, Age) VALUES (source.ID, source.Name, source.Age) WHEN NOT MATCHED BY SOURCE THEN DELETE;

優勢

  • 通過單一的MERGE語句完成數據的插入、更新和刪除操作,避免了使用多個INSERTUPDATEDELETE語句。
  • 適合用于數據倉庫的ETL操作。

注意

  • MERGE操作的執行可能較慢,尤其是在處理大量數據時,因此在使用時需要特別注意性能問題。

四、索引優化:創建合適的索引

為什么需要索引?

索引可以加速查詢操作,尤其是在查詢條件中涉及大量數據的情況下。如果沒有索引,SQL Server會掃描整個表,導致查詢性能低下。

創建索引的基本語法

CREATE INDEX index_name ON table_name (column1, column2, ...);

例子:為Employees表的DepartmentID列創建索引

CREATE INDEX IX_DepartmentID ON Employees(DepartmentID);

覆蓋索引

覆蓋索引(Covering Index)是指包含查詢所需的所有列的索引。在某些查詢中,SQL Server可以僅通過索引查找數據,而無需回到數據表進行檢索,從而提高性能。

CREATE INDEX IX_CoveringIndex ON Employees(DepartmentID, Salary, EmployeeName);

優勢

  • 提高查詢性能,尤其是對于大數據量的表。
  • 減少了查詢時的磁盤I/O操作。

注意

  • 創建索引時需要權衡空間和性能的消耗,過多的索引會導致插入、更新和刪除操作的性能下降。
  • 根據實際查詢的特點,選擇合適的列進行索引創建。

五、查詢優化:避免不必要的DISTINCTGROUP BY

為什么要避免DISTINCT

DISTINCT操作通常需要對整個結果集進行排序和去重,可能會消耗大量的計算資源。對于某些查詢,尤其是涉及大數據量時,DISTINCT會導致不必要的性能損失。

例子

假設我們有一個訂單表Orders,查詢不重復的客戶ID。

SELECT DISTINCT CustomerID FROM Orders;

這個查詢本質上是對所有CustomerID進行去重。在某些情況下,我們可以通過其他方式優化:

SELECT CustomerID FROM Orders GROUP BY CustomerID;

優勢

  • 在處理大數據時,避免使用DISTINCTGROUP BY,可以減少不必要的計算負擔。
  • 可以通過索引優化查詢性能。

注意

  • 在查詢中使用DISTINCTGROUP BY時,需要確保它們的必要性和效率,避免不必要的性能浪費。

六、優化查詢:使用查詢計劃

查詢計劃是什么?

查詢計劃是SQL Server生成的一個操作計劃,描述了如何執行一個SQL查詢。通過分析查詢計劃,可以優化SQL查詢的執行路徑,從而提高查詢性能。

查看查詢計劃

可以使用SET SHOWPLAN_ALL命令查看查詢的執行計劃:

SET SHOWPLAN_ALL ON; GO SELECT * FROM Orders WHERE CustomerID = 'ALFKI'; GO 
SET SHOWPLAN_ALL OFF;

優勢

  • 通過分析查詢計劃,可以了解查詢的瓶頸,并對數據庫進行索引、統計信息等優化。
  • 可以通過SQL Server Management Studio(SSMS)中的“實際執行計劃”選項,直觀地查看查詢的執行步驟。

注意

  • 查詢計劃僅適用于優化查詢的性能,而不是優化數據庫設計或架構。

七、使用 PARTITION BY 優化分區查詢

什么是分區查詢?

在SQL Server中,PARTITION BY 是窗口函數的一部分,它能夠按照特定的列對數據進行分區,然后對每個分區進行獨立的計算。通過分區,你可以實現更加靈活且高效的查詢。

例子:按部門計算每個員工的薪資排名

SELECT EmployeeName,DepartmentID, Salary, RANK() OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS Rank 
FROM Employees;

優勢

  • 提高查詢性能:通過分區,SQL Server能夠更快速地處理分組后的數據,而不需要進行全表掃描。
  • 優化查詢邏輯:當你需要對每個分區的數據進行計算時,PARTITION BY 是非常有用的工具。

注意

  • 分區查詢特別適用于復雜的聚合或排序操作,如分組排名、分區求和等。

八、避免使用 SELECT *,明確列出需要的字段

為什么要避免 SELECT *

雖然使用 SELECT * 可以快速獲取表中的所有列數據,但它通常會導致不必要的性能開銷,特別是當表非常大或包含許多不必要的列時。使用 SELECT * 還可能導致列的冗余提取,影響數據庫I/O操作。

例子:明確列出查詢需要的字段

假設有一張用戶表Users,你只需要查詢UserNameEmail字段:

SELECT UserName, Email FROM Users;

與之相對,以下查詢使用了 SELECT *

SELECT * FROM Users;

優勢

  • 減少數據傳輸量:只獲取需要的字段,避免了多余的列數據傳輸和I/O負擔。
  • 提高查詢效率:減少了數據庫在執行查詢時的計算工作量。

注意

  • 在表結構發生變化時,SELECT * 可能導致意外的行為,因此在開發時要避免使用它,而是明確列出查詢所需的字段。

九、優化子查詢:避免使用嵌套的SELECT語句

為什么要避免嵌套查詢?

嵌套查詢在某些情況下會導致性能瓶頸,尤其是在大數據量時。嵌套的 SELECT 查詢通常會導致SQL Server多次掃描表,尤其是子查詢返回的結果集非常大時。

例子:使用連接代替嵌套查詢

假設我們有兩張表:OrdersCustomers,需要查詢所有下過訂單的客戶信息。

使用嵌套查詢:

SELECT CustomerID, CustomerName 
FROM Customers WHERE CustomerID IN (SELECT CustomerID FROM Orders);

使用連接:

SELECT DISTINCT C.CustomerID,C.CustomerName 
FROM Customers C JOIN Orders O ON C.CustomerID = O.CustomerID;

優勢

  • 減少多次掃描:通過連接代替嵌套查詢,減少了SQL Server在執行過程中多次掃描相同的數據表。
  • 提高性能:在復雜查詢中,連接查詢通常比嵌套查詢更高效,尤其是當連接的列有索引時。

注意

  • 當處理較大的數據集時,連接查詢往往比嵌套查詢要快,但需要確保連接條件的正確性,避免笛卡爾積等錯誤結果。

十、使用 INEXISTS 時的優化選擇

INEXISTS 的區別

INEXISTS 都用于測試某個條件是否滿足,但它們在執行時有不同的效率表現。通常情況下,EXISTS 在處理大數據量時比 IN 更高效,因為 IN 會將子查詢的結果集全部加載到內存中,而 EXISTS 會在找到第一個匹配項時停止執行。

例子:使用 EXISTS 代替 IN

假設我們需要查詢那些下過訂單的客戶:

SELECTCustomerID, CustomerName 
FROM Customers C
WHERE EXISTS (SELECT 1 FROM Orders O WHERE O.CustomerID = C.CustomerID);

相反,使用 IN 的查詢如下:

SELECT CustomerID, CustomerName 
FROM Customers 
WHERE CustomerID IN (SELECT CustomerID FROM Orders);

優勢

  • 性能提升:對于大型數據集,EXISTS 通常比 IN 更高效,因為它在找到匹配時就會停止。
  • 減少內存占用EXISTS 不需要將整個子查詢結果集加載到內存中,而是實時檢查條件。

注意

  • 如果子查詢的返回結果非常小(如一個小范圍的ID集合),IN 的性能可能與 EXISTS 相當,甚至更好。
  • 對于大型子查詢,優先選擇 EXISTS

十一、批量更新和刪除操作優化

為什么需要批量操作?

在大數據量的操作中,直接進行全表的 UPDATEDELETE 可能會導致數據庫鎖定、性能下降等問題。為了避免這些問題,可以將操作拆分成多個小批次進行。

例子:分批刪除數據

假設我們需要刪除Orders表中所有過期的訂單數據,但由于數據量過大,直接刪除會導致性能問題。我們可以采用批量刪除的方式:

SET ROWCOUNT 1000; -- 每次刪除1000條記錄 
DELETE FROM Orders WHERE OrderDate < '2022-01-01'; SET ROWCOUNT 0; -- 恢復默認行為

優勢

  • 減少鎖競爭:分批次操作可以減少對數據庫表的鎖定,避免長時間占用資源。
  • 提高性能:分批操作可以減少每次操作的數據量,優化數據庫的執行時間。

注意

  • 批量操作需要根據實際數據量進行合理調整,避免一次性操作過多數據導致系統資源消耗過大。

十二、優化聯接(JOIN)操作

使用合適的連接類型

在SQL中,我們通常使用 INNER JOINLEFT JOINRIGHT JOINFULL JOIN 來連接多個表。在選擇連接類型時,理解各個連接的使用場景對優化查詢至關重要。

優化 INNER JOIN

INNER JOIN 是最常見的連接類型,它只返回兩個表中匹配的記錄。如果可能,使用 INNER JOIN 優化查詢,因為它通常比其他類型的連接要高效。

SELECT O.OrderID,C.CustomerName 
FROM Orders O 
INNER JOIN Customers C ON O.CustomerID = C.CustomerID;
使用 OUTER JOIN 時的優化

OUTER JOIN 可以返回左表或右表中沒有匹配的記錄,但它通常比 INNER JOIN 更慢。只有在確實需要包含無匹配項的記錄時,才使用 OUTER JOIN

優勢

  • 更高效的連接:使用 INNER JOIN 優化查詢,尤其在數據表索引良好的情況下。
  • 減少數據量:如果只需要返回匹配記錄,盡量使用 INNER JOIN 來提高查詢效率。

注意

  • 對于較大的數據集,尤其是當涉及 LEFT JOINRIGHT JOIN 時,要特別關注性能,確保數據庫設計和索引優化良好。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72422.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72422.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72422.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ES批量查詢

在 Elasticsearch 中&#xff0c;multi_search&#xff08;也稱為 msearch&#xff09;是一種允許你在單個請求中執行多個搜索操作的 API。它可以顯著減少網絡開銷&#xff0c;尤其是在需要執行多個查詢時。multi_search 會將多個查詢打包成一個請求發送給 Elasticsearch&#…

安裝 cnpm 出現 Unsupported URL Type “npm:“: npm:string-width@^4.2.0

Unsupported URL Type "npm:": npm:string-width^4.2.0 可能是 node 版本太低了&#xff0c;需要安裝低版本的 cnpm 試試 npm cache clean --force npm config set strict-ssl false npm install -g cnpm --registryhttps://registry.npmmirror.com 改為 npm insta…

計算機基礎面試(數據庫)

1. 事務的ACID特性&#xff1f;如何通過日志保證原子性和持久性&#xff1f; 專業解答&#xff1a; ACID&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔離性&#xff08;Isolation&#xff09;、持久性&#xff08;Dura…

fastjson1.2.24 CVE-2017-18349 漏洞復現

fastjson1.2.24 CVE-2017-18349 漏洞復現 時間不等人啊/(ㄒoㄒ)/~~ 0. 前置知識 建議直接看參考鏈接 JNDI&#xff1a;Java命名和目錄接口 RMI&#xff1a;遠程方法調用注冊表 LDAP&#xff1a;輕量級目錄訪問協議 CORBA&#xff1a;公共對象請求代理體系結構 1. jndi …

【計算機視覺】手勢識別

手勢識別是計算機視覺領域中的重要方向&#xff0c;通過對攝像機采集的手部相關的圖像序列進行分析處理&#xff0c;進而識別其中的手勢&#xff0c;手勢被識別后用戶就可以通過手勢來控制設備或者與設備交互。完整的手勢識別一般有手的檢測和姿態估計、手部跟蹤和手勢識別等。…

Leetcode 37: 解數獨

Leetcode 37: 解數獨 是經典的回溯算法問題&#xff0c;考察如何利用遞歸和剪枝高效求解數獨問題。這題主要考察對回溯、遞歸、深度優先搜索 (DFS)、剪枝優化等算法思想的掌握。 題目描述 給定一個部分填充的數獨&#xff08;9 x 9&#xff09;網格&#xff0c;用一個有效的算…

VSCode 移除EmmyLua插件的紅色波浪線提示

VSCode 中安裝插件EmmyLua&#xff0c;然后打開lua文件的時候&#xff0c;如果lua代碼引用了C#腳本的變量&#xff0c;經常出現 “undefined global variable: UnityEngineEmmyLua(undefined-global)” 的紅色波浪線提示&#xff0c;這個提示看著比較煩人&#xff0c;我們可以通…

【音視頻】視頻基本概念

一、視頻的基本概念 1.1 視頻碼率&#xff08;kb/s&#xff09; 視頻碼率是指視頻文件在單位時間內使用的數據流量&#xff0c;也叫碼流率。碼率越大&#xff0c;說明單位時間內取樣率越大&#xff0c;數據流進度也就越高 1.2 視頻幀率&#xff08;fps&#xff09; 視頻幀率…

Grafana服務安裝并啟動

Grafana服務安裝并啟動 1、介紹2、下載Grafana3、解壓縮文件4、啟動Grafana服務5、增加數據源,填寫Prometheus訪問地址6、增加圖表 1、介紹 Grafana是一個開源的可視化系統監控和警報工具包。 2、下載Grafana 介紹&#xff1a;Grafana是一個開源的可視化系統監控和警報工具包…

如何將hf-mirror.com作為vllm默認的下載源? conda如何移除虛擬環境?conda 如何復制一份虛擬環境?

前言 上回咱說道,如果你沒辦法訪問huggingface.co,則可以把modelscope作為vllm默認的下載源。 但如果你非得用你用不了的huggingface.co呢?那你可以考慮將hf-mirror.com作為vllm默認的下載源。這里,hf-mirror.com和huggingface.co的效果是一樣的。 要將hf-mirror.com設為v…

MySQL零基礎教程14—子查詢

子查詢比較簡單&#xff0c;我們還是通過案例引入。 有時候我們查詢的時候&#xff0c;需要用到的不止一個表的數據&#xff0c;比如下面的場景&#xff1a; 查詢名字叫李曉紅同學的班主任姓名 我們提供三個表的基礎信息如下&#xff1a; 從三張表的結構&#xff0c;我們不難…

基于單片機和Wifi技術的智能臺燈設計

摘要 &#xff1a;本文主要介紹了基于單片機AT89C51和Wifi技術的智能臺燈的硬件和軟件設計。該智能臺燈具有根據當前光線自動調節燈光亮度的功能&#xff0c;還可對用戶使用臺燈時處于非正常的距離和姿態時給予報警提示&#xff0c;用戶可以隨時通過手機app查詢智能臺燈的報警記…

最新版AI大模型面試八股文

1、主流的開源大模型體系有哪些&#xff0c;并簡要介紹它們的特點&#xff1f; 這個問題考察面試者對當前大模型生態的了解&#xff0c;包括如 Transformer-based 模型&#xff08;如 BERT, GPT 系 列&#xff09;、T5、Switch Transformer 等&#xff0c;以及它們的架構特點和…

在MySQL拿到一條慢SQL語句要如何優化?

在工作的過程中&#xff0c;很多時候會發現執行業務邏輯的時候&#xff0c;某一條SQL語句執行得非常慢。這時候&#xff0c;要如何處理這條語句&#xff0c;如何判斷語句慢的地方在哪里&#xff1f; 一、初級排查 EXPLAIN慢SQL分析 MySQL官網用法&#xff1a; https://dev.mys…

leetcode hot 100 239. 滑動窗口最大值

給你一個整數數組 nums&#xff0c;有一個大小為 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。 返回 滑動窗口中的最大值 。 示例 1&#xff1a; 輸入&#xff1a;nums [1,3,-1,-3,5,3,6,7], k 3 輸…

Leetcode 189: 輪轉數組

Leetcode 189: 輪轉數組 這是一道經典問題&#xff0c;題目要求將一個數組向右輪轉 k 個位置&#xff0c;有多種解法可以快速求解&#xff0c;既可以通過額外空間&#xff0c;也可以在 O(1) 的空間復雜度內完成。本題考察數組操作、雙指針&#xff0c;以及算法優化能力。 題目…

優選算法的智慧之光:滑動窗口專題(二)

專欄&#xff1a;算法的魔法世界?????? 個人主頁&#xff1a;手握風云 目錄 一、例題講解 1.1. 最大連續1的個數 III 1.2. 找到字符串中所有字母異位詞 1.3. 串聯所有單詞的子串 1.4. 最小覆蓋子串 一、例題講解 1.1. 最大連續1的個數 III 題目要求是二進制數組&am…

Linux系統安裝Azure CLI完全指南

引言 Azure CLI是管理Azure云服務的重要命令行工具。本文將詳細介紹在Linux系統上安裝Azure CLI的兩種方法,并提供版本管理、故障排除等完整解決方案。 © ivwdcwso (ID: u012172506) 一、安裝前準備 1.1 系統要求 支持的Linux發行版: Ubuntu 20.04/22.04 LTSDebian 10/…

2025嵌入式軟件開發工程師--音頻方向

一、選擇題&#xff08;每題3分&#xff0c;共30分&#xff09; 1.以下哪個不是C語言中的關鍵字?&#xff08; &#xff09; A. int B. Float C. Define D. Return 2.以下代碼的輸出是: &#xff08; &#xff09; inta 5, b 10; printf("%d“, a b); A. 15 B.16 …

TCP/IP四層模型:從入門到精通

第一部分&#xff1a;基礎概念 1.1 什么是TCP/IP&#xff1f; - TCP/IP 是互聯網的基礎通信協議簇&#xff0c;定義了數據如何在網絡中傳輸和路由。 - 與OSI七層模型的對比&#xff1a;TCP/IP更簡化&#xff0c;分為四層&#xff0c;注重實際應用。 1.2 四層模型結構 1. 應…