如何为LEFT JOIN创造一个条件?

时间:2017-10-27 09:50:45

标签: php mysql

表&#34>动物":

| id | category | category_id |
|:---|---------:|:-----------:|
| 1  |   horses |     1       |    
| 2  |   horses |     2       |
| 3  |     dogs |     1       |
表"马":

| id | name  | 
|:---|------:|
| 1  | james |    
| 2  |  john |   
| 3  |  alan |    
表"狗":

| id | name   | 
|:---|-------:|
| 1  |   lara |    
| 2  | freddy |   
| 3  |  puppy |    

我想根据类别从不同的表中获取名称:

 $pdo = $db->prepare('SELECT *
     FROM animals 
     LEFT JOIN dogs ON animals.category_id = dogs.id
     LEFT JOIN horses ON animals.category_id = horses.id
  ');

while ($row = $pdo->fetch(PDO::FETCH_ASSOC)) {
 echo "Category: ".$row["category"].", Name: ".$row["name"];
}

我需要的结果:

Category: Horses, Name: James
Category: Horses, Name: John
Category: Dogs, Name: Lara

我现在的问题是,如何确定一个类别是"马"我想只从"马"获得数据,如果某个类别是"狗"我只想从"狗"获取数据。因为在这里" category_id"具有相同的价值。

2 个答案:

答案 0 :(得分:3)

一对一连接

我建议改变你的桌子:

表动物:

| id | name | category_id |
|:---|-----:|:-----------:|
| 1  | John |      1      |
| 2  | Mary |      1      |
| 3  |  Rex |      2      |

表类别:

| id |  type |
|:---|------:|
| 1  | Horse |
| 2  |   Dog |
| 3  |   Cat |

(在类型字段上放置一个'唯一'索引;这样你就不会多次输入相同的类型)

然后使用以下查询(就我个人而言,我会包含'animals.id'以使代码更容易)

SELECT animals.id, animals.name, categories.type as category
FROM animals
LEFT JOIN animals.category_id = categories.id

这样您就可以获得所需的数据:

| id | name | category |
|:---|-----:|:---------|
| 1  | John | Horse    |
| 2  | Mary | Horse    |
| 3  |  Rex | Dog      |

这样,您就可以从动物到类别表进行一对一的连接。

一对多连接

如果你想包括,比如说它们已被喂食,你可以通过增加2个表来创建一对多连接:

表animals_feedings(这是一个链接表):

| id | animals_id | feedings_id |
|:---|:----------:|:-----------:|
| 1  |      1     |      1      |
| 2  |      1     |      2      |
| 3  |      1     |      5      |
| 4  |      3     |      3      |
| 5  |      2     |      4      |
| 6  |      2     |      2      |
| 7  |      2     |      5      |

(为了加快以后的选择,我建议在两个* _id列的每一列上放一个索引供以后使用)

表格输入:

| id | comment    |
|:---|:-----------|
| 1  | 1 apple    |
| 2  | grass      |
| 3  | dry food   |
| 4  | 2 apples   |
| 5  | hay        |

(在评论字段中放置一个“唯一”索引;这样你就不能多次输入相同的评论并在评论字段上放置一个索引(为了加快INSERT IGNORE INTO查询的速度)有数千或数百万条记录),只要确保它是一个char字段,而不是varchar(不是100%确定这是否仍然重要,但char有一个固定的大小,因此可以更容易预测索引))

这样,您可以以标准化的方式存储您的评论(最好插入这些评论是通过“INSERT IGNORE INTO feedings”-query,这样您最终不会在重复评论上浪费空间)

要获取此数据,您可以简单地执行此操作:

SELECT animals.id,
       animals.name,
       categories.type as category,
       TRIM(GROUP_CONCAT(' ', feedings.comment)) as feedings
FROM animals
LEFT JOIN categories ON animals.category_id = categories.id
LEFT JOIN animals_feedings ON animals.id = animals_id
LEFT JOIN feedings ON animals_feedings.feedings_id = feedings.id
GROUP BY animals.id

或使用别名使您的SQL查询更具可读性:

SELECT a.id,
       a.name,
       c.type as category,
       TRIM(GROUP_CONCAT(' ', f.comment)) as feedings
FROM animals a
LEFT JOIN categories c ON a.category_id = c.id
LEFT JOIN animals_feedings af ON a.id = af.animals_id
LEFT JOIN feedings f ON af.feedings_id = f.id
GROUP BY a.id

通过这种方式,您可以将动物列表和提要注释组合到一个字段中:

| id | name | category | feedings             | 
|---:|:-----|:---------|:---------------------| 
|  1 | John | Horse    | hay, grass, 1 apple  | 
|  2 | Mary | Horse    | hay, grass, 2 apples | 
|  3 | Rex  | Dog      | dry food             | 

了解如何规范化数据非常重要,尤其是当您的数据库投入使用多年的应用程序时。

我希望这有帮助!

答案 1 :(得分:2)

首先,您的表格不一致。您的category_id不应该对马匹和狗都有相同的ID。

无论如何,如果不能更改模式,那么您可以使用以下解决方法:

Select * from
(select *from animals where category = 'horses') animals
Left Join horses on animals.category_id = horses.id

union all

Select * from
(select *from animals where category = 'dogs') animals
Left Join dogs on animals.category_id = dogs.id

希望它有所帮助!