理解mysql執行多表聯合查詢


閱讀目錄

查詢多張表一般有如下連接方法:

1)內連接:join, inner join
2)外連接:left join, left outer join, right join, right outer join, union;
3) 交叉連接:cross join

join的含義是:用於多表中字段直接的聯系。

基本語法如下:

select * from table1 inner|left|right join table2 on conditiona

說明:table1 是指第一張表。table2是指第二張表。 on 后面的含義是:滿足這個條件。

join按照功能可以分成如下三類:

1) inner join(內連接,或叫等值連接):取得兩個表中存在連接匹配關系的記錄。
2)left join(左連接):取得左表(table1)完全記錄,右表(table2)如果有條件相符合的記錄就匹配,否則為null;
3) right join(右連接): 取得右表(table2)完全記錄,左表(table1)如果有條件相符合的記錄就匹配,否則為null;

我們來看一個列子:

如下是user1表和user2表中的數據如下所示:

一:inner join(內連接)

基本語法如下:

select * from user inner join user2 on user.age = user2.age;

如上代碼的含義是:查詢user表和user2表(內連接) 通過on后面的條件查詢,user表中的age字段 等於 user2表中的age這個條件滿足的話,才會把兩個表中的數據都查詢出來的,否則的話,查詢數據就是空哦。如下所示:

二:left join(左連接)

基本語法如下:

select * from user left join user2 on user.age = user2.age;

如上代碼的含義是:如果user表中的age字段值 等於 user2表中的age字段的值的話,那么就會把所有的數據都查詢出來,如果該表中的字段age值不相等的話,那么user表中的記錄會全部查詢出來,user2表中的所有字段為null值。

如下所示:

三:right join(右連接)

基本語法如下:

select * from user right join user2 on user.age = user2.age;

和上面的 left join 的含義相反,就是說 如果條件相等的話,就會把兩張表的數據都查詢出來,如果不相等的話,就會把第二張表的數據查詢出來,第一張表的數據字段值為null.

如下所示:

四:cross join(交叉連接)

交叉連接,得到的結果是兩個表的乘積; 效果和 inner join 類似,如下所示:

五:union操作

select * from user left join user2 on user.username = user2.username union select * from user right join user2 on user.username = user2.username;

上面代碼的含義是:查詢user表和user2表,如果該兩張表的username值相等的話,使用left join(左鏈接) 和 right join(右連接),如果都相等的話,就把兩張表所有的數據查詢出來。否則的話,兩張表字段不相等的話,那么第一個條件 left join查詢后的數據就是 按照user表查詢出所有的數據,user2表中的數據字段值為null;union的含義的意思可以理解為或者的意思,我們可以理解它為or的意思,第二個條件是使用 right join 連接符,意思是如果username字段不相等的話,就按照第二張表的數據全部查詢出來,第一張表的所有字段查詢值為null。如下所示:

六:node+mysql 多表聯合查詢

在mysql模塊中,我們可以使用Connection對象的query方法的第一個參數編寫sql語句來執行多表聯合查詢,但是如果在sql語句中指定了相同的字段(比如相同的字段在不同的表中),那么在默認的情況下,后面的字段會覆蓋前面的字段查詢出來的數據。從而不是我們想要的結果。我們是想要把這兩張表的數據同時查詢出來。為了演示下,我們新建兩張表,一張是user表,該表有4個字段,分別是id,username, password, age; 另外一張表是user2表,該表有四個字段,分別是id,username,password,age等字段。如下所示:

我們現在使用Connection對象的query方法結合查詢這兩張表中的所有數據,查詢語句如下:

select * from user inner join user2 where user.age = user2.age;

因此所有的代碼如下所示:

const mysql = require('mysql');
/*
 createConnection方法創建一個表示與Mysql數據庫服務器之間連接的 Connection對象
*/
const connection = mysql.createConnection({
  host: 'localhost',
  port: 3306,
  database: 'my_db',
  user: 'root',
  password: '123456'
});

/*
 connection 對象被創建之后,可以使用該對象的 connect方法建立mysql數據庫服務器之間的連接
*/
connection.connect((err) => {
  if (err) {
    console.log(err);
    console.log('數據庫連接失敗');
  } else {
    console.log('數據庫連接成功');
    const sql = 'select * from user inner join user2 where user.age = user2.age';
    connection.query(sql, (err, res) => {
      if (err) {
        console.log('查詢數據失敗');
      } else {
        console.log(res);
        connection.end();
      }
    }); 
  }
});

然后我們在命令行中,運行 node app.js 后,可以看到如下所示:

如上圖我們可以看到,查詢后的數據就是user2表中的數據,user1表的數據被覆蓋了,因為user表中的字段和user2表中的字段是一樣的,雖然在不同的表中,但是因為字段一樣,后面的user2表會把user表中的字段覆蓋掉。

解決方法有如下幾種:

1. 第一種是給sql語句重復的字段使用別名。這種方法比較繁瑣,因為如果表中有多個字段相同的話,要設置多個別名。這種方法不折騰。

2. 第二種方法為在query方法中使用 nestTables屬性,並將屬性值設置為true。因此會將兩個表中的數據以兩個對象的形式輸出來。如下sql語句改為如下:

{
  sql: 'select * from user inner join user2 where user.age = user2.age',
  nestTables: true
}

代碼如下:

const mysql = require('mysql');
/*
 createConnection方法創建一個表示與Mysql數據庫服務器之間連接的 Connection對象
*/
const connection = mysql.createConnection({
  host: 'localhost',
  port: 3306,
  database: 'my_db',
  user: 'root',
  password: '123456'
});

/*
 connection 對象被創建之后,可以使用該對象的 connect方法建立mysql數據庫服務器之間的連接
*/
connection.connect((err) => {
  if (err) {
    console.log(err);
    console.log('數據庫連接失敗');
  } else {
    console.log('數據庫連接成功');
    const sql = {
      sql: 'select * from user inner join user2 where user.age = user2.age',
      nestTables: true
    };
    connection.query(sql, (err, res) => {
      if (err) {
        console.log('查詢數據失敗');
      } else {
        console.log(res);
        connection.end();
      }
    }); 
  }
});

然后我們運行結果如下所示:

如上圖可以看到,包含兩個對象user和user2,對象里面是各自的數據。

3. 第三種方法是為在query方法中使用nestTables屬性並將屬性值設定為一個分割字符,這會將被結合的兩張表中的數據以一個對象的形式輸出。該對象的屬性名 為 字段所屬表名+分割字符+字段名。

sql語句改為如下:

{
  sql: 'select * from user inner join user2 where user.age = user2.age',
  nestTables: '_'
}

所有代碼如下:

const mysql = require('mysql');
/*
 createConnection方法創建一個表示與Mysql數據庫服務器之間連接的 Connection對象
*/
const connection = mysql.createConnection({
  host: 'localhost',
  port: 3306,
  database: 'my_db',
  user: 'root',
  password: '123456'
});

/*
 connection 對象被創建之后,可以使用該對象的 connect方法建立mysql數據庫服務器之間的連接
*/
connection.connect((err) => {
  if (err) {
    console.log(err);
    console.log('數據庫連接失敗');
  } else {
    console.log('數據庫連接成功');
    const sql = {
      sql: 'select * from user inner join user2 where user.age = user2.age',
      nestTables: '_'
    };
    connection.query(sql, (err, res) => {
      if (err) {
        console.log('查詢數據失敗');
      } else {
        console.log(res);
        connection.end();
      }
    }); 
  }
});

然后運行結果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM