MySQL - 自连接



MySQL 自连接

MySQL 自连接用于将一个表连接到自身,就好像该表是两个表一样。为此,至少需要在 MySQL 语句中临时重命名一个表。

自连接是一种内部连接,当需要比较同一表中的两列时执行;可能是为了建立它们之间的关系。换句话说,当表中同时包含外键主键时,表就会与自身连接。

但是,与其他连接的查询不同,我们使用 WHERE 子句来指定表与自身组合的条件;而不是 ON 子句。

语法

以下是 MySQL 中自连接的基本语法:

SELECT column_name(s)
FROM table1 a, table1 b
WHERE a.common_field = b.common_field;

这里,WHERE 子句可以是根据您的需求给出的任何表达式。

示例

自连接只需要一个表连接自身;因此,让我们创建一个 CUSTOMERS 表,其中包含客户详细信息,例如他们的姓名、年龄、地址以及他们赚取的薪水。

CREATE TABLE CUSTOMERS (
   ID INT NOT NULL,
   NAME VARCHAR (20) NOT NULL,
   AGE INT NOT NULL,
   ADDRESS CHAR (25),
   SALARY DECIMAL (18, 2),       
   PRIMARY KEY (ID)
);

现在使用 INSERT 语句将值插入此表,如下所示:

INSERT INTO CUSTOMERS VALUES
(1, 'Ramesh', 32, 'Ahmedabad', 2000.00 ),
(2, 'Khilan', 25, 'Delhi', 1500.00 ),
(3, 'Kaushik', 23, 'Kota', 2000.00 ),
(4, 'Chaitali', 25, 'Mumbai', 6500.00 ),
(5, 'Hardik', 27, 'Bhopal', 8500.00 ),
(6, 'Komal', 22, 'Hyderabad', 4500.00 ),
(7, 'Muffy', 24, 'Indore', 10000.00 );

该表将创建如下:

ID NAME AGE ADDRESS SALARY
1 Ramesh 32 Ahmedabad 2000.00
2 Khilan 25 Delhi 1500.00
3 Kaushik 23 Kota 2000.00
4 Chaitali 25 Mumbai 6500.00
5 Hardik 27 Bhopal 8500.00
6 Komal 22 Hyderabad 4500.00
7 Muffy 24 Indore 10000.00

现在,让我们使用以下自连接查询连接此表。我们的目标是根据客户的收入在所述客户之间建立关系。我们借助 WHERE 子句来实现这一点。

SELECT a.ID, b.NAME as EARNS_HIGHER, a.NAME as EARNS_LESS, 
a.SALARY as LOWER_SALARY FROM CUSTOMERS a, CUSTOMERS b
WHERE a.SALARY < b.SALARY;

输出

显示的结果表将列出所有收入低于其他客户的客户:

ID EARNS_HIGHER EARNS_LESS LOWER_SALARY
2 Ramesh Khilan 1500.00
2 Kaushik Khilan 1500.00
6 Chaitali Komal 4500.00
3 Chaitali Kaushik 2000.00
2 Chaitali Khilan 1500.00
1 Chaitali Ramesh 2000.00
6 Hardik Komal 4500.00
4 Hardik Chaitali 6500.00
3 Hardik Kaushik 2000.00
2 Hardik Khilan 1500.00
1 Hardik Ramesh 2000.00
3 Komal Kaushik 2000.00
2 Komal Khilan 1500.00
1 Komal Ramesh 2000.00
6 Muffy Komal 4500.00
5 Muffy Hardik 8500.00
4 Muffy Chaitali 6500.00
3 Muffy Kaushik 2000.00
2 Muffy Khilan 1500.00
1 Muffy Ramesh 2000.00

带有 ORDER BY 子句的自连接

此外,在使用自连接将表与自身连接后,组合表中的记录也可以使用 ORDER BY 子句按升序排序。以下是它的语法:

SELECT column_name(s)
FROM table1 a, table1 b
WHERE a.common_field = b.common_field
ORDER BY column_name;

示例

在此示例中,执行以下查询将使用自连接在 WHERE 子句上将 CUSTOMERS 表与自身连接。然后,使用 ORDER BY 子句相对于指定的列按升序排列记录。在这里,我们根据 salary 列排列记录

SELECT  a.ID, b.NAME as EARNS_HIGHER, a.NAME as EARNS_LESS, 
a.SALARY as LOWER_SALARY FROM CUSTOMERS a, CUSTOMERS b
WHERE a.SALARY < b.SALARY ORDER BY a.SALARY;

输出

结果表显示如下:

ID EARNS_HIGHER EARNS_LESS LOWER_SALARY
2 Ramesh Khilan 1500.00
2 Kaushik Khilan 1500.00
2 Chaitali Khilan 1500.00
2 Hardik Khilan 1500.00
2 Komal Khilan 1500.00
2 Muffy Khilan 1500.00
3 Chaitali Kaushik 2000.00
1 Chaitali Ramesh 2000.00
3 Hardik Kaushik 2000.00
1 Hardik Ramesh 2000.00
3 Komal Kaushik 2000.00
1 Komal Ramesh 2000.00
3 Muffy Kaushik 2000.00
1 Muffy Ramesh 2000.00
6 Chaitali Komal 4500.00
6 Hardik Komal 4500.00
6 Muffy Komal 4500.00
4 Hardik Chaitali 6500.00
4 Muffy Chaitali 6500.00
5 MuffyHardik 8500.00

使用客户端程序的自连接

我们还可以使用客户端程序对一个或多个表执行自连接操作。

语法

要通过 PHP 程序执行自连接,我们需要使用mysqli函数query()执行 SQL 查询,如下所示:

$sql = 'SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b 
WHERE a.tutorial_author = b.tutorial_author';
$mysqli->query($sql);

要通过 JavaScript 程序执行自连接,我们需要使用mysql2库的query()函数执行 SQL 查询,如下所示:

sql = "SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b 
WHERE a.tutorial_author = b.tutorial_author";
con.query(sql);  

要通过 Java 程序执行自连接,我们需要使用JDBC函数executeQuery()执行 SQL 查询,如下所示:

String sql = "SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b 
WHERE a.tutorial_author = b.tutorial_author";
statement.executeQuery(sql);

要通过 python 程序执行自连接,我们需要使用MySQL Connector/Pythonexecute()函数执行 SQL 查询,如下所示:

self_join_query = "SELECT a.ID, b.NAME as EARNS_HIGHER, a.NAME as EARNS_LESS, a.SALARY as LOWER_SALARY
FROM CUSTOMERS a, CUSTOMERS b WHERE a.SALARY < b.SALARY"
cursorObj.execute(self_join_query)

示例

以下是程序:

$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'TUTORIALS';
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
if ($mysqli->connect_errno) {
    printf("Connect failed: %s
", $mysqli->connect_error); exit(); } // printf('Connected successfully.
'); $sql = 'SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b WHERE a.tutorial_author = b.tutorial_author'; $result = $mysqli->query($sql); if ($result->num_rows > 0) { echo " following is the details after executing SELF join! \n"; while ($row = $result->fetch_assoc()) { printf("Id: %s, Title: %s, Author: %s, Count: %d", $row["tutorial_id"], $row["tutorial_title"], $row["tutorial_author"], $row["tutorial_count"]); printf("\n"); } } else { printf('No record found.
'); } mysqli_free_result($result); $mysqli->close();

输出

获得的输出如下:

following is the details after executing SELF join!
Id: 3, Title: JAVA Tutorial, Author: Sanjay, Count: 1   
var mysql = require("mysql2");
var con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "password",
}); //Connecting to MySQL

con.connect(function (err) {
  if (err) throw err;
  //   console.log("Connected successfully...!");
  //   console.log("--------------------------");
  sql = "USE TUTORIALS";
  con.query(sql);

  //Self Join
  sql = "SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b 
  WHERE a.tutorial_author = b.tutorial_author";
  con.query(sql, function (err, result) {
    if (err) throw err;
    console.log(result);
  });
});      

输出

产生的输出如下所示:

[
  {
    tutorial_id: 1,
    tutorial_title: 'Learn PHP',
    tutorial_author: 'John Poul',
    tutorial_count: 2
  }
]
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class SelfJoin {
   public static void main(String[] args) {
      String url = "jdbc:mysql://127.0.0.1:3306/TUTORIALS";
      String username = "root";
      String password = "password";
      try {
         Class.forName("com.mysql.cj.jdbc.Driver");
         Connection connection = DriverManager.getConnection(url, username, password);
         Statement statement = connection.createStatement();
         System.out.println("Connected successfully...!");

         //MySQL Self JOIN...!;
         String sql = "SELECT a.tutorial_id, a.tutorial_title, a.tutorial_author, b.tutorial_count FROM tutorials_tbl a, tcount_tbl b 
         WHERE a.tutorial_author = b.tutorial_author";
         ResultSet resultSet = statement.executeQuery(sql);
         System.out.println("Table records after Self Join...!");
         while (resultSet.next()){
            System.out.println(resultSet.getString(1)+ " "+ resultSet.getString(2)+" "+resultSet.getString(3));
         }
         connection.close();
      } catch (Exception e) {
         System.out.println(e);
      }
   }
} 

输出

获得的输出如下所示:

Connected successfully...!
Table records after Self Join...!
1 Learn PHP John Paul
3 JAVA Tutorial Sanjay
import mysql.connector
#establishing the connection
connection = mysql.connector.connect(
    host='localhost',
    user='root',
    password='password',
    database='tut'
)
cursorObj = connection.cursor()
self_join_query = f"""SELECT a.ID, b.NAME as EARNS_HIGHER, a.NAME as EARNS_LESS, a.SALARY as LOWER_SALARY
FROM CUSTOMERS a, CUSTOMERS b WHERE a.SALARY < b.SALARY"""
cursorObj.execute(self_join_query)
# Fetching all the rows that meet the criteria
filtered_rows = cursorObj.fetchall()
for row in filtered_rows:
    print(row)
cursorObj.close()
connection.close()  

输出

以下是上述代码的输出:

(4, 'Ramesh', 'Chaital', Decimal('1200.00'))
(6, 'Khilan', 'Komal', Decimal('7000.00'))
(4, 'Khilan', 'Chaital', Decimal('1200.00'))
(1, 'Khilan', 'Ramesh', Decimal('4000.00'))
(7, 'kaushik', 'Muffy', Decimal('10000.00'))
(6, 'kaushik', 'Komal', Decimal('7000.00'))
(5, 'kaushik', 'Hardik', Decimal('10000.00'))
(4, 'kaushik', 'Chaital', Decimal('1200.00'))
(2, 'kaushik', 'Khilan', Decimal('8000.00'))
(1, 'kaushik', 'Ramesh', Decimal('4000.00'))
(6, 'Hardik', 'Komal', Decimal('7000.00'))
(4, 'Hardik', 'Chaital', Decimal('1200.00'))
(2, 'Hardik', 'Khilan', Decimal('8000.00'))
(1, 'Hardik', 'Ramesh', Decimal('4000.00'))
(4, 'Komal', 'Chaital', Decimal('1200.00'))
(1, 'Komal', 'Ramesh', Decimal('4000.00'))
(6, 'Muffy', 'Komal', Decimal('7000.00'))
(4, 'Muffy', 'Chaital', Decimal('1200.00'))
(2, 'Muffy', 'Khilan', Decimal('8000.00'))
(1, 'Muffy', 'Ramesh', Decimal('4000.00'))
广告