MySQL多表查詢中的笛卡爾積問題


精選專欄鏈接 🔗


  • MySQL技術筆記專欄
  • Redis技術筆記專欄
  • 大模型搭建專欄
  • Python學習筆記專欄
  • 深度學習算法專欄

歡迎訂閱,點贊+關注,每日精進1%,與百萬開發者共攀技術珠峰

更多內容持續更新中!希望能給大家帶來幫助~ 😀😀😀


MySQL多表查詢中的笛卡爾積問題

  • 1,為什么需要多表查詢
  • 2,什么是笛卡爾積
  • 3,多表查詢的笛卡爾積錯誤
    • 3.1,笛卡爾積錯誤案例
    • 3.2,笛卡爾積錯誤的分析和解決
    • 3.3,公共字段的處理
  • 練習


1,為什么需要多表查詢

多表查詢,也稱為關聯查詢,指兩個或更多個表一起完成查詢操作。

可進行多表查詢的前提條件: 這些一起查詢的表之間是有關系的(一對一、一對多),它們之間一定是有關聯字段,比如:員工表和部門表,這兩個表依靠“部門編號”進行關聯。

案例說明為什么需要多表查詢:

如下圖所示的是一個項目的三張表:EMPLOYEES表(員工表)、DEPARTMENTS表、LOCATIONS表。

在這里插入圖片描述
顯然,我們可以得到如下信息:

  • EMPLOYEES 表和DEPARTMENTS表通過 department_id 字段相關聯;
  • DEPARTMENT表和 LOCATIONS 表通過 location_id 字段相關聯;

如果我們現在有一個新需求:要求查詢員工名為 “Abel” 的人在哪個城市工作?

顯然 EMPLOYEES 表中沒有城市這個字段,城市字段位于 LOCATIONS 表內。
我們可以通過如下步驟完成此需求。

第一步:在EMPLOYEES表內查詢Abel的員工信息

SQL語句如下:

SELECT * 
FROM employees
WHERE last_name = 'Abel';

運行結果如下:

在這里插入圖片描述
可以看到Abel 所在的 department_id 為80。

第二步:在DEPARTMENT表內查詢department_id 為80的部門信息

SQL語句如下:

SELECT *
FROM departments
WHERE department_id = 80;

運行結果如下:

在這里插入圖片描述
可以看到department_id 為80的部門對應的location_id是2500。

第二步:在LOCATIONS表內查詢location_id是2500的地址信息

SQL語句如下:

SELECT *
FROM locations 
WHERE location_id = 2500;

運行結果如下:

在這里插入圖片描述
由此可見,員工Abel的工作城市是Oxford


寫了三條SQL語句才實現此需求,找到了Abel的工作城市,這樣是很不方便的,而且在高并發的系統中,執行多個SQL語句對效率和性能的影響是比較大的(相當于多次交互)。因此要引入多表查詢,通過多表查詢可以實現 一條SQL語句完成此需求。


2,什么是笛卡爾積

笛卡爾乘積是一個數學運算。假設我有兩個集合 X 和 Y,那么 X 和 Y 的笛卡爾積就是 X 和 Y 的所有可能組合,也就是第一個對象來自于 X,第二個對象來自于 Y 的所有可能。組合的個數即為兩個集合中元素個數的乘積數。如下圖所示:

在這里插入圖片描述


3,多表查詢的笛卡爾積錯誤

多表查詢的一個常見錯誤就是笛卡爾積錯誤。


3.1,笛卡爾積錯誤案例

當我們有如下需求時:

需求:查詢每一位員工的employee_id和department_name。

注意: 如下圖所示,員工的employee_id位于EMPLOYEES表,而department_name字段位于DEPARTMENTS表。

在這里插入圖片描述

如果執行如下SQL語句,得到的是錯誤結果:

SELECT employee_id,department_name
FROM employees,departments;  

運行結果如下:

在這里插入圖片描述

一共查詢出2889條記錄,而EMPLOYEES表有107條記錄;DEPARTMENTS表有27條記錄。27?107=2889,它把每個員工都與每個部門匹配了一遍,顯然這是一種錯誤的實現方式,具體來說是出現了笛卡爾積的錯誤。

錯誤的原因是:缺少了多表的連接條件。


3.2,笛卡爾積錯誤的分析和解決

笛卡爾積錯誤會在下面條件下產生:

  • 省略多個表的連接條件(或關聯條件);
  • 連接條件(或關聯條件)失效;
  • 所有表中的所有行互相連接;

正確的多表查詢需要有連接條件。為了避免笛卡爾積錯誤,可以通過WHERE子句加入有效的連接條件。

加入連接條件后的查詢語法如下:

SELECT table1.column, table2.column
FROM  table1, table2
WHERE table1.column1 = table2.column2;  #連接條件

因此,正確的SQL語句應該是:

SELECT employee_id,department_name
FROM employees,departments
# 兩個表的連接條件
WHERE employees.department_id = departments.department_id;

運行結果如下:

在這里插入圖片描述

此時查詢得到的結果才是正常的。

注意:如上SQL查詢得到106條記錄,而EMPLOYEES表內有107條記錄,原因是EMPLOYEES表中存在一條記錄的 department_id 字段為Null。

在這里插入圖片描述


3.3,公共字段的處理

一個細節問題是:如果查詢語句中出現了多個表中都存在的字段,則必須指明此字段所在的表。接下來結合案例解釋:

需求:查詢每一位員工的employee_id、department_name、department_id。

如果執行如下SQL:

SELECT employee_id,department_name,department_id
FROM employees,departments
WHERE employees.`department_id` = departments.department_id;

執行報錯:

在這里插入圖片描述

原因是:EMPLOYEES表和DEPARTMENTS表都存在字段 departmen_id,SQL語句中沒有明確指出查詢哪個表中的 departmen_id 字段。

因此正確的SQL語句是:

# 如果查詢語句中出現了多個表中都存在的字段,則必須指明此字段所在的表。
SELECT employee_id,department_name,employees.department_id
FROM employees,departments
WHERE employees.`department_id` = departments.department_id;

運行結果如下:

在這里插入圖片描述
我們了解到,如果查詢語句中出現了多個表中都存在的字段,則必須指明此字段所在的表。對此規則進行拓展:從sql優化的角度,建議多表查詢時,每個字段前都指明其所在的表。

因為如果不指明字段所在的表,MySQL會自己去兩張表中找此字段,找到后還需要檢查另外一張表中是否存在此字段。這會在一定程度上影響查詢的性能。因此建議多表查詢時,每個字段前都指明其所在的表。

即,更好的SQL語句如下:

SELECT employees.employee_id,departments.department_name,employees.department_id
FROM employees,departments
WHERE employees.`department_id` = departments.department_id;

練習

我們再提出一個新的需求用做練習。

需求:查詢每一位員工的employee_id、last_name、department_name、city。

在這里插入圖片描述

SQL語句如下:

SELECT e.employee_id,e.last_name,d.department_name,l.city,e.department_id,l.location_id
FROM employees e,departments d,locations l
WHERE e.`department_id` = d.`department_id`
AND d.`location_id` = l.`location_id`;

因此可以總結出規律:如果有n個表實現多表的查詢,則需要至少n-1個連接條件。


在這里插入圖片描述

歡迎訂閱,點贊+關注,每日精進1%,與百萬開發者共攀技術珠峰

更多內容持續更新中!希望能給大家帶來幫助~ 😀😀😀

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

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

相關文章

深度解析 HTML `loading` 屬性:優化網頁性能的秘密武器

在開發網頁時,我常常被頁面加載速度慢的問題困擾,尤其是在圖片和嵌入內容較多的頁面上。用戶還沒看到內容就可能因為等待時間過長而離開,這對用戶體驗和 SEO 都是致命打擊。后來,我發現了 HTML 的 loading 屬性——一個簡單卻強大…

[C/C++內存安全]_[中級]_[安全處理字符串]

場景 在現代C開發指南出來后,并不建議使用C的某些內存不安全的字符串處理函數。那么有哪些函數不安全? 說明 內存安全方面,肯定是要向Rust看齊的。使用標準std::string字符串類,很大情況能避免緩沖區溢出問題。 如果舊項目里有…

【CNN】卷積神經網絡- part1

1.卷積1.局部連接定義:只是于輸入數據的一部分區域相連,每個神經元只關注一小部分作用:模仿人類的視野機制,極大的減少了模型參數的數量,降低了計算成本2.權重共享定義:所有神經元使用相同的權重向量來檢測…

漏洞生命周期管理:從發現到防護的全流程方案

漏洞并非孤立存在,而是遵循 “發現→評估→修復→驗證→閉環” 的生命周期。多數企業安全事件的根源并非缺乏漏洞發現能力,而是對漏洞生命周期的管理缺失 —— 大量漏洞被發現后長期未修復,或修復后未驗證效果。構建全流程漏洞生命周期管理體…

opencv圖像基本操作解析與實操

圖片操作cv2.namedWindow() 創建命名窗口cv2.imshow()顯示窗口cv2.destroyAllwindws()摧毀窗口cv2.resizeWindow()改變窗口大小cv2.waitKey()等待用戶輸入cv2.imread()讀取圖像img.shape 圖片h、w、c(高、寬、通道數import cv2 # opencv讀取的格式是BGR import m…

kafka--基礎知識點--6.1--LEO、HW、LW

在 Apache Kafka 中,LEO(Log End Offset)、HW(High Watermark)、和 LW(Low Watermark) 是副本機制和日志管理中的核心概念,共同確保數據一致性、可見性和存儲效率。以下是它們的詳細…

在線深凹槽深檢測方法都有哪些 —— 激光頻率梳 3D 輪廓檢測

引言在制造業中,深凹槽深度的精確檢測是保證零部件質量的關鍵環節。隨著智能制造的推進,在線檢測需求日益迫切,傳統檢測方法在效率和精度上的不足逐漸顯現。本文將梳理在線深凹槽深的傳統檢測方法,并重點探討激光頻率梳 3D 輪廓檢…

NumPy 數組拼接的高級技巧與實踐

在數據處理和機器學習領域,NumPy 是 Python 中最核心的科學計算庫之一。NumPy 數組(ndarray)的拼接操作是數據預處理中極為常見的需求。本文將深入探討如何將不同形狀的 NumPy 數組進行拼接,特別是如何將多個一維數組與二維數組進…

原創-基于 PHP 和 MySQL 的證書管理系統 第三版

第一版屬于開源版本,所以后臺功能沒有開發許多出來,今天分享證書查詢第三版; 通過幾天的緊急寫代碼及測試;第三版基本可以上線上,不過后面有一些BUG只能一邊修復。 演示地址:物星科云證書管理系統 第三版…

爬蟲虛擬環境

conda create --name myrepenv python3.12創建一個名為 myrepenv、Python 版本為 3.12 的全新 Conda 虛擬環境,適合需要隔離依賴或測試不同 Python 版本的項目。我的方式創建(需要指定盤符)conda create --prefixD:\Anaconda3\envs\myrepenv python3.12展示所下的co…

Netty集群方案詳解與實戰(Zookeeper + Redis + RabbitMQ)

一、背景 二、Netty 單體架構的優缺點 優點 缺點 三、Netty 集群架構的優缺點 優點 缺點 四、適用場景對比 五、Netty單體架構代碼實現 六、Netty集群架構方案實現 方案一、Nginx負載均衡實現集群(較為簡單) Nginx配置 前端連接方式 方案二、NacosGateway(結合…

Oracle遷移到高斯,查詢字段默認小寫,解決辦法

一、問題說明 Oracle中,查詢結果字段默認大寫。高斯中,查詢結果字段默認小寫。在Mybatis的xml中,如果查詢語句使用Map接收查詢結果,使用resultType"java.util.HashMap"或resultType"Map"等寫法,返…

Android Jetpack Compose + MVVM 開發流程深度分析

核心組件關系圖 [View] -- 觀察 --> [ViewModel] -- 操作 --> [Repository]| | Compose UI StateFlow/LiveData| | 用戶交互事件 Room/Retrofit| …

Tailwind CSS快速上手 Tailwind CSS的安裝、配置、使用

📚前言 在Web前端開發的歷史長河中,CSS的編寫方式經歷了多次演進,從早期的原生CSS 到 CSS預處理(Less/Sass/Stylus) 到 CSS-in-JS(Styled-Components/Emotion) 再到 Utility-First 原子化CSS。每一種演進方案其本質都是圍繞“開發效率”、“…

單例模式的智慧:從UVM看控制的藝術

有時候,生活中的很多東西其實只需要一個就夠了,就像一個公司只需要一個CEO,一個王朝只需要一個皇帝。在UVM驗證環境中,也有很多這樣的需求——有些對象,我們希望它在整個仿真過程中只存在一個實例。這就是我們今天要聊…

Hexo - 免費搭建個人博客01 - 安裝軟件工具

導言我的博客:https://q164129345.github.io/ Hexo 作為一個 Node.js 框架,它依賴于 Node.js 運行時環境來執行。 一、安裝Node.js官方網址:https://nodejs.org/zh-cn追求系統穩定性、可靠性以及希望減少維護頻率的用戶來說,LTS版…

【Kubernetes】集群啟動nginx,觀察端口映射,work節點使用kubectl配置

參考b站叩丁狼總結:完整版Kubernetes(K8S)全套入門微服務實戰項目,帶你一站式深入掌握K8S核心能力 在master節點執行 kubectl create deployment nginx --imagenginxkubectl expose deployment nginx --port80 --typeNodePort1. …

20250704-基于強化學習在云計算環境中的虛擬機資源調度研究

基于強化學習在云計算環境中的虛擬機資源調度研究 隨著云計算規模的持續擴大,數據中心虛擬機資源調度面臨動態負載、異構資源適配及多目標優化等挑戰。傳統啟發式算法在復雜場景下易陷入局部最優,而深度強化學習(DRL)憑借序貫決策…

day 33打卡

day 21 常見的降維算法 # 先運行之前預處理好的代碼 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings(ignore)# 設置中文字體 plt.rcParams[font.sans-serif] [SimHei] plt.rcParam…

sec(x)積分推導

在MATLAB中繪制 sec?(x)、cos(x) 和 ln?∣sec?(x)tan?(x)∣的函數圖像,需要特別注意 sec?(x) 在 cos?(x)0(即 xπ/2kπ)處的奇點。(deepseek生成代碼)% 定義x范圍(-2π到2π),…