自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

八個(gè)不可不知的SQL高級(jí)方法

數(shù)據(jù)庫
通過深入了解SQL的高級(jí)特性和技巧,您可以更有效地進(jìn)行數(shù)據(jù)分析和管理,為您的工作帶來更大的價(jià)值。

結(jié)構(gòu)化查詢語言(SQL)是一種廣泛使用的工具,用于管理和操作數(shù)據(jù)庫。基本的SQL查詢簡單易學(xué),但掌握高級(jí)SQL技術(shù)可以將您的數(shù)據(jù)分析和管理能力提升到新的高度。

高級(jí)SQL技術(shù)是指一系列功能和函數(shù),使您能夠?qū)?shù)據(jù)執(zhí)行復(fù)雜操作,例如聚合、連接、子查詢、窗口函數(shù)和遞歸查詢。

通過深入了解SQL的高級(jí)特性和技巧,您可以更有效地進(jìn)行數(shù)據(jù)分析和管理,為您的工作帶來更大的價(jià)值。

本文將詳細(xì)介紹以下技術(shù),并使用具體且易于理解的示例。

1. 窗口函數(shù)

窗口函數(shù)支持在與當(dāng)前行相關(guān)的一組行上執(zhí)行計(jì)算,可以根據(jù)指定的窗口定義進(jìn)行聚合、排序和分析操作。這種計(jì)算方式可以提供更靈活和精確的數(shù)據(jù)分析能力。

例如;有一個(gè)名為orders的表,其中包含以下列:order_id、customer_id、order_date和order_amount。您想要計(jì)算每個(gè)客戶的銷售總額,按其訂單日期排序。您可以使用SUM窗口函數(shù)來實(shí)現(xiàn)這一點(diǎn):

SELECT order_id, customer_id, order_date, order_amount,
  SUM(order_amount) OVER (
    PARTITION BY customer_id
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS running_total
FROM orders;

在此示例中,SUM函數(shù)應(yīng)用于order_amount列,并按customer_id列進(jìn)行分區(qū)。這意味著每個(gè)客戶的累計(jì)銷售額將分別計(jì)算。

ORDER BY子句指定應(yīng)使用訂單日期來確定每個(gè)分區(qū)內(nèi)行的順序。這意味著將按客戶訂單的順序計(jì)算累計(jì)銷售額。

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW子句指定計(jì)算的窗口框架應(yīng)包括從分區(qū)開始到當(dāng)前行為止的所有行。這意味著將從每個(gè)客戶的第一筆訂單開始計(jì)算累計(jì)銷售額,直到包括當(dāng)前訂單。

查詢的結(jié)果將是一個(gè)包含與orders表相同列的表,以及一個(gè)名為running_total的附加列,其中包含每個(gè)客戶的累計(jì)銷售額,按其訂單日期排序。

通過在SQL中使用窗口函數(shù),您可以對(duì)數(shù)據(jù)執(zhí)行復(fù)雜計(jì)算,并深入了解業(yè)務(wù)。此示例演示了如何為每個(gè)客戶計(jì)算累計(jì)銷售額,但是您可以使用窗口函數(shù)執(zhí)行許多其他類型的計(jì)算,例如計(jì)算移動(dòng)平均值、排名數(shù)據(jù)等。

2. 公共表達(dá)式(CTEs)

公共表達(dá)式(CTEs)支持您在SQL查詢中定義一個(gè)臨時(shí)結(jié)果集,并將其命名為一個(gè)表,以便在后續(xù)的SQL語句中引用和使用該臨時(shí)結(jié)果集。這種方式可以提高查詢的可讀性和可維護(hù)性,并使查詢邏輯更加模塊化和靈活。

假設(shè)有一個(gè)名為employees的表,其中包含以下列:employee_id、employee_name、department_id和salary。您想要計(jì)算每個(gè)部門的平均工資,然后找到其工資高于部門平均工資的員工。為此,您可以使用CTE首先計(jì)算每個(gè)部門的平均工資,然后在第二個(gè)查詢中使用該CTE查找其工資高于部門平均工資的員工。

WITH department_avg_salary AS (
  SELECT department_id, AVG(salary) AS avg_salary
  FROM employees
  GROUP BY department_id
)

SELECT employee_id, employee_name, salary, department_avg_salary.avg_salary
FROM employees
INNER JOIN department_avg_salary ON employees.department_id = department_avg_salary.department_id
WHERE salary > department_avg_salary.avg_salary;

在此示例中,第一個(gè)查詢定義了一個(gè)名為department_avg_salary的CTE。該CTE使用AVG函數(shù)和GROUP BY子句計(jì)算每個(gè)部門的平均工資,將員工按其部門分組。

然后,第二個(gè)查詢將department_avg_salary CTE視為表格,并將其與employees表格在department_id列上連接。結(jié)果由WHERE子句過濾,僅包括其工資高于其部門平均工資的員工。在這種情況下使用CTE的優(yōu)點(diǎn)在于它允許您將問題分解為兩個(gè)步驟:首先計(jì)算每個(gè)部門的平均工資,然后選擇其工資高于其部門平均工資的員工。通過將計(jì)算分成兩個(gè)步驟,查詢更易于閱讀和維護(hù)。

CTEs也可以用于許多其他情況,例如遞歸查詢、復(fù)雜連接等。通過使用CTE,您可以使SQL查詢更易于閱讀和理解。

3. 聚合函數(shù)

聚合函數(shù)是用于對(duì)一組值進(jìn)行計(jì)算并返回單個(gè)結(jié)果值的函數(shù)。它們可以在表的多行或多列之間執(zhí)行計(jì)算,并且能夠以有意義的方式對(duì)數(shù)據(jù)進(jìn)行匯總。在SQL中,最常見的聚合函數(shù)包括SUM(求和)、AVG(平均值)、MIN(最小值)、MAX(最大值)和COUNT(計(jì)數(shù))。這些函數(shù)在數(shù)據(jù)分析和報(bào)告中非常實(shí)用,可以幫助我們快速獲得對(duì)數(shù)據(jù)集的總結(jié)統(tǒng)計(jì)信息。

例如,有一個(gè)名為sales的表,其中包含以下列:sale_id、product_id、sale_date、sale_amount和region。您想要計(jì)算每個(gè)產(chǎn)品的總銷售額和平均銷售額,以及每個(gè)地區(qū)的暢銷產(chǎn)品。為此,您可以使用聚合函數(shù)按產(chǎn)品和地區(qū)分組銷售,并計(jì)算總銷售額和平均銷售額,以及找到每個(gè)地區(qū)的暢銷產(chǎn)品。

SELECT 
  product_id, 
  AVG(sale_amount) AS avg_sale_amount, 
  SUM(sale_amount) AS total_sale_amount, 
  region, 
  RANK() OVER (PARTITION BY region ORDER BY SUM(sale_amount) DESC) AS rank
FROM sales
GROUP BY product_id, region;

在此示例中,查詢有三個(gè)聚合函數(shù):AVG、SUM和RANK。

AVG函數(shù)計(jì)算每個(gè)產(chǎn)品和地區(qū)的平均銷售額,而SUM函數(shù)計(jì)算每個(gè)產(chǎn)品和地區(qū)的總銷售額。GROUP BY子句按產(chǎn)品和地區(qū)分組銷售。

RANK函數(shù)用于查找每個(gè)地區(qū)的暢銷產(chǎn)品。OVER子句指定應(yīng)單獨(dú)對(duì)每個(gè)地區(qū)進(jìn)行排名,而PARTITION BY子句指定要對(duì)數(shù)據(jù)進(jìn)行分區(qū)的列(在本例中為region)。ORDER BY子句指定排名應(yīng)基于每個(gè)地區(qū)中每種產(chǎn)品的銷售金額總和,并按降序排列。

查詢結(jié)果包括product_id、region、total_sale_amount、avg_sale_amount和rank列。rank列指示每個(gè)地區(qū)中每種產(chǎn)品基于總銷售額的排名,排名第一的暢銷產(chǎn)品在每個(gè)地區(qū)都是1。

使用聚合函數(shù),在這種情況下,優(yōu)點(diǎn)在于它們允許您對(duì)數(shù)據(jù)進(jìn)行分組和匯總,并計(jì)算有用的指標(biāo),例如總銷售額和平均銷售額。RANK函數(shù)還允許您查找每個(gè)地區(qū)的暢銷產(chǎn)品,這對(duì)于識(shí)別趨勢和改進(jìn)機(jī)會(huì)非常有用。

聚合函數(shù)也可以用于許多其他情況,例如計(jì)算最小值和最大值、計(jì)數(shù)記錄等。通過使用聚合函數(shù),您可以使SQL查詢更加強(qiáng)大和靈活。

4. 透視表

透視表是一種用于從較大的表格中進(jìn)行數(shù)據(jù)匯總和聚合,以便更方便進(jìn)行分析的表格。它可以將數(shù)據(jù)從行轉(zhuǎn)換為列,并以更有意義的方式展示數(shù)據(jù)。

在SQL中,我們可以使用PIVOT運(yùn)算符創(chuàng)建透視表。該運(yùn)算符可以根據(jù)指定的列對(duì)數(shù)據(jù)進(jìn)行匯總,并以表格的形式呈現(xiàn)結(jié)果,使數(shù)據(jù)更易于理解和分析。透視表為我們提供了一種靈活且直觀的方式來匯總和展示數(shù)據(jù),從而幫助我們更好地理解數(shù)據(jù)的關(guān)系和趨勢。

例如:

SELECT 
  customer_id, 
  [1] AS Product1, 
  [2] AS Product2, 
  [3] AS Product3, 
  [4] AS Product4, 
  [5] AS Product5
FROM (
  SELECT 
    customer_id, 
    product_id, 
    order_quantity
  FROM orders
) p
PIVOT (
  SUM(order_quantity)
  FOR product_id IN ([1], [2], [3], [4], [5])
) AS pvt;

在上面的示例中,查詢使用PIVOT運(yùn)算符按產(chǎn)品ID旋轉(zhuǎn)數(shù)據(jù),每個(gè)客戶都有一個(gè)列。SUM函數(shù)用于計(jì)算每個(gè)客戶訂購的每種產(chǎn)品的總數(shù)量。

子查詢p用于從orders表中提取必要的列。然后將PIVOT運(yùn)算符應(yīng)用于子查詢,使用SUM函數(shù)計(jì)算每個(gè)客戶訂購的每種產(chǎn)品的總數(shù)量。FOR子句指定了透視列(在本例中為product_id),而IN子句指定了要透視的值(在本例中為[1]、[2]、[3]、[4]、[5])。

查詢的結(jié)果是一個(gè)透視表,顯示了每個(gè)客戶訂購的每種產(chǎn)品的總數(shù)量,每種產(chǎn)品都有一列,每個(gè)客戶都有一行。

透視表也可以用于許多其他情況,例如匯總銷售數(shù)據(jù)、分析調(diào)查結(jié)果等。通過使用透視表,您可以使SQL查詢更加強(qiáng)大和靈活。

5. 子查詢

SQL中的子查詢是用于從一個(gè)或多個(gè)表中檢索數(shù)據(jù)的嵌套查詢,子查詢的結(jié)果在主查詢中使用。它們可用于過濾、排序和分組數(shù)據(jù),并可分類為單行或多行子查詢。子查詢括在括號(hào)中,可以在SQL語句的各個(gè)部分中使用,例如SELECT、FROM、WHERE和HAVING子句。

例如;有兩個(gè)名為employees和salaries的表。employees表包含以下列:employee_id、first_name、last_name和department_id。salaries表包含以下列:employee_id、salary和salary_date。您想要找到每個(gè)部門工資最高的員工的姓名。為此,您可以使用子查詢查找每個(gè)部門的最高工資,然后將結(jié)果與employees和salaries表連接以獲取具有該工資的員工的姓名。

下面的查詢使用子查詢查找每個(gè)部門的最高工資。首先執(zhí)行子查詢并返回包含每個(gè)部門最高工資的結(jié)果集。然后,主查詢將employees和salaries表與子查詢的結(jié)果連接,以獲取每個(gè)部門工資最高的員工的姓名。

SELECT 
  e.first_name, 
  e.last_name, 
  e.department_id, 
  s.salary
FROM 
  employees e 
  INNER JOIN salaries s ON e.employee_id = s.employee_id 
  INNER JOIN (
    SELECT 
      department_id, 
      MAX(salary) AS max_salary
    FROM 
      salaries
    GROUP BY 
      department_id
  ) m ON s.department_id = m.department_id AND s.salary = m.max_salary;

使用INNER JOIN子句將employees和salaries表連接起來,使用employee_id列作為連接鍵。使用department_id列將子查詢連接到主查詢,并使用salary列匹配每個(gè)部門的最高工資。

查詢的結(jié)果是一個(gè)表格,顯示每個(gè)部門工資最高的員工的姓名及其部門ID和工資。

6. 交叉連接

交叉連接是一種連接操作,用于返回兩個(gè)或多個(gè)表的所有可能行組合,而不需要連接條件。它在生成測試數(shù)據(jù)或需要獲取多個(gè)表格所有可能組合的計(jì)算時(shí)非常有用。然而,由于交叉連接可能會(huì)產(chǎn)生高計(jì)算成本和龐大的結(jié)果集,因此在使用時(shí)需要謹(jǐn)慎考慮其影響,并確保結(jié)果集的大小符合預(yù)期。通常情況下,應(yīng)優(yōu)先考慮使用其他類型的連接操作,如內(nèi)連接、外連接或等值連接,以更有效地獲取所需的數(shù)據(jù)。

在下面的示例中,有兩個(gè)名為customers和orders的表。customers表包含以下列:customer_id、customer_name和city。orders表包含以下列:order_id、customer_id和order_date。您想要找到每個(gè)客戶在每個(gè)城市下單的總數(shù)。為此,您可以使用交叉連接生成一個(gè)結(jié)果集,將每個(gè)客戶與每個(gè)城市組合,然后將結(jié)果與orders表連接以獲取每種組合的訂單數(shù)量。

SELECT 
  c.customer_id, 
  c.customer_name, 
  c.city, 
  COUNT(o.order_id) AS order_count
FROM 
  customers c 
  CROSS JOIN (
    SELECT DISTINCT 
      city
    FROM 
      customers
  ) cities 
  LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE 
  c.city = cities.city
GROUP BY 
  c.customer_id, 
  c.customer_name, 
  c.city;

示例中,查詢使用交叉連接生成一個(gè)結(jié)果集,該結(jié)果集將每個(gè)客戶與每個(gè)城市組合在一起。交叉連接首先執(zhí)行,返回一個(gè)包含每個(gè)客戶和城市的每個(gè)組合的結(jié)果集。然后,主查詢使用左連接將交叉連接的結(jié)果與orders表連接,以確保即使客戶沒有下訂單也包括所有客戶在結(jié)果中。

WHERE子句用于過濾結(jié)果,僅包括客戶所在城市與交叉連接中的城市匹配的行。這確保了結(jié)果僅顯示每個(gè)客戶在其各自城市中的訂單數(shù)量。

GROUP BY子句用于按客戶ID、客戶名稱和城市分組結(jié)果。COUNT()函數(shù)用于計(jì)算每個(gè)客戶在每個(gè)城市中的訂單數(shù)量。

查詢的結(jié)果是一個(gè)表格,顯示了每個(gè)客戶在每個(gè)城市中下達(dá)的訂單總數(shù)。

7. 臨時(shí)表

SQL中的臨時(shí)表是在執(zhí)行SQL語句或事務(wù)期間創(chuàng)建和使用的表。它們存儲(chǔ)在內(nèi)存或磁盤上,并在創(chuàng)建它們的會(huì)話結(jié)束或不再需要時(shí)自動(dòng)刪除。臨時(shí)表通常用于存儲(chǔ)中間結(jié)果,或?qū)?fù)雜查詢分解為更小、更易管理的部分。

它們可以使用CREATE TEMPORARY TABLE語句創(chuàng)建,并像常規(guī)表一樣使用SQL命令(如SELECT、INSERT、UPDATE和DELETE)進(jìn)行操作。臨時(shí)表可以非常有用,用于優(yōu)化復(fù)雜查詢并提高性能,因?yàn)樗鼈兛梢詭椭鷾p少需要在任何給定時(shí)間處理的數(shù)據(jù)量。

假設(shè)有一個(gè)名為sales的表,其中包含以下列:date、product、category和sales_amount。您想創(chuàng)建一個(gè)報(bào)告,顯示過去一年每個(gè)月每個(gè)類別的總銷售額。為此,您可以使用一個(gè)臨時(shí)表來創(chuàng)建每個(gè)月銷售數(shù)據(jù)的摘要,然后將臨時(shí)表與sales表連接,以獲取每個(gè)類別的總銷售額。

首先,您可以使用CREATE TEMPORARY TABLE語句創(chuàng)建臨時(shí)表:

CREATE TEMPORARY TABLE monthly_sales_summary (
  month DATE,
  category VARCHAR(50),
  total_sales DECIMAL(10,2)
);

此語句創(chuàng)建了一個(gè)名為monthly_sales_summary的臨時(shí)表,其中包含三列:month、category和total_sales。month列的類型為DATE,category列的類型為VARCHAR(50),total_sales列的類型為DECIMAL(10,2)。

接下來,使用INSERT INTO語句將摘要數(shù)據(jù)填充到臨時(shí)表中:

INSERT INTO monthly_sales_summary (month, category, total_sales)
SELECT 
  DATE_TRUNC('month', date) AS month,
  category,
  SUM(sales_amount) AS total_sales
FROM 
  sales
WHERE 
  date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
GROUP BY 
  DATE_TRUNC('month', date),
  category;

此語句使用DATE_TRUNC函數(shù)將date列截?cái)嗟皆路菁?jí)別,按月份和類別分組銷售數(shù)據(jù)。此查詢的結(jié)果插入到monthly_sales_summary表中,該表現(xiàn)在包含每個(gè)月銷售數(shù)據(jù)的摘要。

最后,可以將臨時(shí)表與sales表連接起來,以獲取每個(gè)類別的總銷售額:

SELECT 
  s.category, 
  mss.month, 
  mss.total_sales
FROM 
  sales s 
  JOIN monthly_sales_summary mss 
    ON s.category = mss.category 
    AND DATE_TRUNC('month', s.date) = mss.month
WHERE 
  s.date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
ORDER BY 
  s.category, 
  mss.month;

此語句將sales表與monthly_sales_summary表連接在category和month列上,并從臨時(shí)表中選擇category、month和total_sales列。WHERE子句用于過濾結(jié)果,僅包括過去一年的銷售數(shù)據(jù),ORDER BY子句用于按類別和月份對(duì)結(jié)果進(jìn)行排序。

查詢的結(jié)果是一個(gè)表格,顯示了過去一年每個(gè)月每個(gè)類別的總銷售額。

8. 具體化視圖

SQL中的具體化視圖是存儲(chǔ)為物理表的預(yù)計(jì)算結(jié)果集。它們基于SQL查詢創(chuàng)建和維護(hù),并用于提高頻繁執(zhí)行查詢的性能。具體化視圖可以按計(jì)劃或按需刷新,以確保數(shù)據(jù)是最新的。當(dāng)針對(duì)具體化視圖執(zhí)行查詢時(shí),結(jié)果集從物理表中檢索,而不是從原始表中計(jì)算。

這可以提升性能,特別是對(duì)于涉及聯(lián)接或聚合函數(shù)的復(fù)雜查詢。具體化視圖通常用于數(shù)據(jù)倉庫和業(yè)務(wù)智能應(yīng)用程序中,在這些應(yīng)用程序中,它們可以幫助加速報(bào)告和儀表板。

例如,有一個(gè)名為sales的大型表,其中包含以下列:date、product、category和sales_amount。您想創(chuàng)建一個(gè)報(bào)告,顯示過去一年每個(gè)月每個(gè)類別的總銷售額。但是,直接在sales表上運(yùn)行此查詢會(huì)很慢,因?yàn)樗瑪?shù)百萬行。為了加快查詢速度,可以創(chuàng)建一個(gè)物化視圖,按月份和類別匯總銷售數(shù)據(jù)。

要?jiǎng)?chuàng)建物化視圖,可以使用CREATE MATERIALIZED VIEW語句,如下所示:

CREATE MATERIALIZED VIEW monthly_sales_summary AS 
SELECT 
  DATE_TRUNC('month', date) AS month,
  category,
  SUM(sales_amount) AS total_sales
FROM 
  sales
WHERE 
  date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
GROUP BY 
  DATE_TRUNC('month', date),
  category;

此語句創(chuàng)建了一個(gè)名為monthly_sales_summary的物化視圖,其中包含每個(gè)月和類別的銷售數(shù)據(jù)摘要。SELECT語句與前面示例中用于創(chuàng)建臨時(shí)表的語句相同,但是不使用臨時(shí)表,而是將結(jié)果存儲(chǔ)在物化視圖中。

物化視圖與表類似,因?yàn)樗鼈儗?shù)據(jù)存儲(chǔ)在磁盤上,但是在基礎(chǔ)數(shù)據(jù)更改時(shí)會(huì)自動(dòng)更新。您可以使用REFRESH MATERIALIZED VIEW語句手動(dòng)刷新物化視圖,也可以使用cron作業(yè)或其他調(diào)度工具設(shè)置定期刷新。

創(chuàng)建物化視圖后,可以像查詢其他表一樣查詢它:

SELECT 
  category, 
  month, 
  total_sales
FROM 
  monthly_sales_summary
ORDER BY 
  category, 
  month;

此語句從monthly_sales_summary物化視圖中選擇category、month和total_sales列,并按類別和月份對(duì)結(jié)果進(jìn)行排序。

在這種情況下使用物化視圖的優(yōu)點(diǎn)在于,它允許您預(yù)計(jì)算和存儲(chǔ)摘要數(shù)據(jù),從而減少運(yùn)行查詢所需的時(shí)間。物化視圖特別適用于經(jīng)常運(yùn)行并需要對(duì)大型數(shù)據(jù)集進(jìn)行復(fù)雜計(jì)算的報(bào)告。但是,它們也有一些限制,例如它們可能占用大量磁盤空間,并且在基礎(chǔ)數(shù)據(jù)更改時(shí)可能無法立即更新。

結(jié)語

掌握高級(jí)SQL技術(shù),如窗口函數(shù)、CTE、聚合函數(shù)、透視表、子查詢、交叉連接、臨時(shí)表和物化視圖,可以幫助您更有效地處理復(fù)雜的數(shù)據(jù)分析任務(wù)。

責(zé)任編輯:趙寧寧 來源: Java學(xué)研大本營
相關(guān)推薦

2023-12-13 18:06:39

微服務(wù)設(shè)計(jì)模式

2023-06-26 14:11:06

SQLC++語言

2010-06-11 14:46:38

可路由協(xié)議

2024-03-21 08:57:39

語言軟件開發(fā)

2010-09-17 15:35:28

互聯(lián)網(wǎng)協(xié)議

2023-09-20 09:00:00

2023-11-13 14:19:57

Golang編程語言

2021-08-12 16:02:22

Jupyter NotPython命令

2020-11-30 13:12:04

Linux文本命令

2015-01-15 09:34:28

2015-07-28 16:48:04

云計(jì)算性能測試云服務(wù)

2015-06-10 10:56:50

iOS開發(fā)技巧

2023-06-15 11:01:43

Java工具開源

2025-01-03 17:10:54

2010-04-16 17:09:18

Oracle查看鎖

2018-06-12 11:05:33

2019-12-02 14:14:20

緩沖系統(tǒng)調(diào)用函數(shù)

2020-11-11 21:27:55

緩沖文件調(diào)用

2014-06-09 13:21:27

2024-09-23 21:05:45

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)