Warm tip: This article is reproduced from serverfault.com, please click

mysql-加入三表codeigniter 4

(mysql - Join three table codeigniter 4)

发布于 2020-07-14 14:46:36

大家好,我是Codeigniter 4的新手,目前正在该项目的一个小项目中工作,我正在尝试加入三个表并在单个表中显示数据。

Table_1
id unique_id Name
1  1111      Sam   
2  2222      Charlote

Table_2
id unique_id Name
1  1212      Jhon 
2  5151      Alex

Table_3
id author title
1  1111   Book_1
2  5151   Book_2
3  1111   Book_3


Result
------------------------
| No | Author | Title  |
------------------------
| 1  | Sam    | Book_1 |
| 2  | Alex   | Book_2 |
| 3  | Sam    | Book_3 |
------------------------

我尝试加入,但没有工作。

        $this->join('Table_1', 'Table_1.unique_id = Table_3.author ');
        $this->join('Table_2', 'Table_2.unique_id = Table_3.author ');
        $this->select('Table_1.Name');
        $this->select('Table_2.Name');
        $this->select('Table_3.*');
        $this->orderBy('Table_3.id');
        return  $this->findAll();

还有其他加入方式吗?谢谢

Questioner
dhannyjsb
Viewed
0
TimBrownlaw 2020-07-15 04:09:44

你当前无法使用的表是因为Table_1和Table_2实际上是同一张表。

尝试并更正以使用LEFT JOIN

public function example_1() {
    $this->join('Table_1', 'Table_1.unique_id = Table_3.author', 'LEFT');
    $this->join('Table_2', 'Table_2.unique_id = Table_3.author', 'LEFT');
    $this->select('Table_1.Name');
    $this->select('Table_2.Name');
    $this->select('Table_3.*');
    $this->orderBy('Table_3.id');
    $result = $this->findAll();

    echo $this->db->getLastQuery();

    return $result;
}

你会得到...

SELECT `Table_1`.`Name`, `Table_2`.`Name`, `Table_3`.*
FROM `Table_3`
LEFT JOIN `Table_1` ON `Table_1`.`unique_id` = `Table_3`.`author`
LEFT JOIN `Table_2` ON `Table_2`.`unique_id` = `Table_3`.`author`
ORDER BY `Table_3`.`id`

array(3) {
  [0]=>
  array(4) {
    ["Name"]=>
    NULL
    ["id"]=>
    string(1) "1"
    ["author"]=>
    string(4) "1111"
    ["title"]=>
    string(6) "Book_1"
  }
  [1]=>
  array(4) {
    ["Name"]=>
    string(4) "Alex"
    ["id"]=>
    string(1) "2"
    ["author"]=>
    string(4) "5151"
    ["title"]=>
    string(6) "Book_2"
  }
  [2]=>
  array(4) {
    ["Name"]=>
    NULL
    ["id"]=>
    string(1) "3"
    ["author"]=>
    string(4) "1111"
    ["title"]=>
    string(6) "Book_3"
  }
}

请注意,查询中有两次出现名称。那么哪一个会赢呢?似乎仅使用Table_2.name,并且对Table_1.name的任何引用均为NULL,因为未使用它。

你可以使用别名为它们指定不同的名称,但是你会得到诸如name_1和name_2之类的名称,那么它是哪一个呢?这是由于你的Table_1和Table_2中有重复项,并且你都要求两者兼而有之。

更好的方法 因此,在这种情况下,你将需要在Table_1和Table_2上执行UNION。

我认为CI查询构建器中没有UNION命令。

使用mysql,它将是...

public function get_book_and_author() {
    $sql = "SELECT Table_3.id, T12.name as author, Table_3.title 
            FROM (
                SELECT Table_1.* FROM Table_1
            UNION
                SELECT Table_2.* FROM Table_2
                ) as T12
            LEFT JOIN Table_3 ON T12.unique_id = Table_3.author  
            WHERE Table_3.author IS NOT NULL
            ";
    $result = $this->db->query($sql);

    return $result->getResultArray();
}

因此,在此示例中,我们在“选择”中指定了你需要的3个字段。请注意,T12.name已重命名为author。(请参见下面的输出)

然后UNION必须在Table_1和Table_2上执行,并且结果(使用别名)被命名为T12(Table_1和Table_2的简写),因为结果需要一个新名称。

然后LEFT JOIN对Table_3执行a,这将给出所有包含NULL的组合,因此WHERE语句使用Table_3.author上的“ IS NOT NULL”过滤掉这些组合。

我省略了ORDER BY因为它并不是真正需要的,如果你愿意,可以将其添加回去。

结果的var_dump()给出...

array(3) {
  [0]=>
  array(3) {
    ["id"]=>
    string(1) "1"
    ["author"]=>
    string(3) "Sam"
    ["title"]=>
    string(6) "Book_1"
  }
  [1]=>
  array(3) {
    ["id"]=>
    string(1) "2"
    ["author"]=>
    string(4) "Alex"
    ["title"]=>
    string(6) "Book_2"
  }
  [2]=>
  array(3) {
    ["id"]=>
    string(1) "3"
    ["author"]=>
    string(3) "Sam"
    ["title"]=>
    string(6) "Book_3"
  }
}

这样,你将获得示例表所要求的每个匹配行的ID,作者和标题。