@
本博客翻譯自兩篇博客的:
- http://www.mysqltutorial.org/mysql-cross-join/
- https://www.w3resource.com/mysql/advance-query-in-mysql/mysql-cross-join.php
1. cross join簡介
MySQL cross join是mysql中的一種連接方式,區別於內連接和外連接,對於cross join連接來說,其實使用的就是笛卡爾連接。在MySQL中,當CROSS JOIN不使用WHERE子句時,CROSS JOIN產生了一個結果集,該結果集是兩個關聯表的行的乘積。通常,如果每個表分別具有n和m行,則結果集將具有n*m行
引用https://www.w3resource.com/mysql/advance-query-in-mysql/mysql-cross-join.php的圖片,如圖演示了cross join的過程,這個過程其實就是笛卡爾連接查詢
2. cross join用法
cross join用法:
SELECT * FROM t1
CROSS JOIN t2;
注意:cross join的時候是不需要on或者using關鍵字的,這個是區別於inner join和join的
如果WHERE在條件表中添加一個子句t1並t2具有關系,則CROSS JOIN該INNER JOIN子句的工作方式類似於以下查詢中所示:
SELECT * FROM t1
CROSS JOIN t2
WHERE t1.id = t2.id;
ok,再列舉一下cross join表作為衍生表的例子
SELECT *
FROM table111
LEFT JOIN(table112 CROSS JOIN table113)
ON table111.id=table113.id;
ok,介紹了cross join的簡單用法,現在拿http://www.mysqltutorial.org/mysql-cross-join/的例子來介紹:
首先,創建一個新數據庫salesdb:
CREATE DATABASE IF NOT EXISTS salesdb;
其次,將當前數據切換到新數據庫testdb:
USE testdb;
在salesdb數據庫中創建新表:
- 該表 products包含產品主數據,其中包括產品ID,產品名稱和銷售價格。
- 該表stores包含出售產品的商店。
- 該表sales包含按數量和日期在特定商店中出售的產品。
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(100),
price DECIMAL(13,2 )
);
CREATE TABLE stores (
id INT PRIMARY KEY AUTO_INCREMENT,
store_name VARCHAR(100)
);
CREATE TABLE sales (
product_id INT,
store_id INT,
quantity DECIMAL(13 , 2 ) NOT NULL,
sales_date DATE NOT NULL,
PRIMARY KEY (product_id , store_id),
FOREIGN KEY (product_id)
REFERENCES products (id)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (store_id)
REFERENCES stores (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
將數據插入三個表中。假設我們有三個產品iPhone,iPad並且Macbook Pro其在兩個商店出售North和South。
INSERT INTO products(product_name, price)
VALUES('iPhone', 699),
('iPad',599),
('Macbook Pro',1299);
INSERT INTO stores(store_name)
VALUES('North'),
('South');
INSERT INTO sales(store_id,product_id,quantity,sales_date)
VALUES(1,1,20,'2017-01-02'),
(1,2,15,'2017-01-05'),
(1,3,25,'2017-01-05'),
(2,1,30,'2017-01-02'),
(2,2,35,'2017-01-05');
ok,業務場景:現在要統計每個商店每種商品總共營業額是多少錢?
很顯然,用SUM(quantity * price),再group by一下就可以,這個sql很好寫
SELECT
sto.`store_name`,
pro.`product_name`,
SUM(quantity * price) AS revenue
FROM
sales sal
INNER JOIN stores sto
ON sto.`id` = sal.`store_id`
INNER JOIN products pro
ON sal.`product_id` = pro.`id`
GROUP BY sto.`store_name`,pro.`product_name`;
ok,看了一下,發現沒賣出的商品是沒統計出來的,所以不太符合業務需求,業務是要統計所有的商店商品,所以可以用cross join笛卡爾連接,得出所有的商店商品組合數據
笛卡爾查詢組合數據sql:
SELECT
a.`store_name`,
b.product_name
from stores cross join products
前面統計sql已經有了,所以將組合數據SQL和統計數據的SQL進行關聯:
SELECT
a.`store_name`,
b.product_name,
IFNULL(c.revenue, 0) AS revenue
FROM
stores a
CROSS JOIN products b
LEFT JOIN
(SELECT
sto.`id` AS store_id,
pro.`id` AS product_id,
sto.`store_name`,
pro.`product_name`,
SUM(quantity * price) AS revenue
FROM
sales sal
INNER JOIN stores sto
ON sto.`id` = sal.`store_id`
INNER JOIN products pro
ON sal.`product_id` = pro.`id`
GROUP BY sto.`store_name`,
pro.`product_name`) c
ON a.id = c.store_id
AND b.id = c.product_id
ORDER BY a.store_name ;
請注意,IFNULL如果收入為NULL (在商店沒有銷售的情況下),查詢使用該函數返回0。
通過CROSS JOIN這種方式使用該子句,您可以回答廣泛的問題,例如,按銷售員,月份查找銷售收入,即使該銷售員在特定月份沒有銷售。
ok,本博客是翻譯兩篇英文博客的:
- http://www.mysqltutorial.org/mysql-cross-join/
- https://www.w3resource.com/mysql/advance-query-in-mysql/mysql-cross-join.php
ok,本博客內容翻譯自兩篇英文博客,不過本博客進行一定修整,將兩篇博客內容進行理解整合成這篇中文博客,原因是這兩篇博客的例子還是不錯的,舉出了cross join的常用使用場景,當然除了兩篇博客提出的用法,cross join因為其笛卡爾連接的特性,還可以用於批量寫數據,對應批量的寫法,可以參考我之前的MySQL博客,本博客性質屬於翻譯的,所以轉載請注明出處