加入两个MySQL表,但附加条件?

时间:2012-05-19 16:26:27

标签: mysql sql

我有两张桌子:

产品:

+-------------------------------------------------+
|   id   |    name   |   category     |   price   |
+-------------------------------------- ----------+
|    1   |    item1  |      1         |   0.99    |
|    2   |    item2  |      2         |   1.99    |
|    3   |    item3  |      3         |   2.95    |
|    4   |    item4  |      4         |   2.50    |
+-------------------------------------------------+

图片:

+--------------------------------------------------+
|   id   |    file_name    |   p_id   |   priority |
+-------------------------------------- -----------+
|    1   |      image1     |     1    |      0     |
|    2   |      image2     |     1    |      1     |
|    3   |      image3     |     2    |      2     |
|    4   |      image4     |     3    |      2     |
|    5   |      image5     |     3    |      3     |
|    11  |      image6     |     3    |      5     |
|    16  |      image7     |     4    |      1     |
|    19  |      image8     |     4    |      7     |
+--------------------------------------------------+

我需要获取所有产品信息,以及产品图像的文件名。请注意,产品可以包含多个图像;我想要一个最低优先级的那个。此外,我只想要特定类别产品的结果。

所以,说我需要类别为{1,2,3}的产品的信息,然后在查询运行后结果应该返回:

+-----------------------------------------------------------------+
|   id   |    name   |   category     |   price   |   file_name   |
+-------------------------------------- ----------+---------------+
|    1   |    item1  |      1         |   0.99    |     image1    |
|    2   |    item2  |      2         |   1.99    |     image3    |
|    3   |    item3  |      3         |   2.95    |     image4    |
+-------------------------------------------------+---------------+

我尝试过编写几个不同的连接语句,但它们都不起作用;这并不奇怪,因为在谈到SQL时我总是新手。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:4)

我将添加一步一步的教程,首先获得正确的连接, 然后添加一些条件来过滤类别,最后进行分组 并使用带有子选择的having子句。您需要使用最后一个选择 在你的代码中。我也在mysql实例上测试了这个并且它可以工作。 我正在使用group,以防你需要其他一些复杂的东西。有一个例子很好。 语法是ansii sql,它应该适用于所有数据库而不仅仅是mysql

-- get everything by joining
select p.*, i.file_name
from products p 
join image i on (p.id = i.p_id)



/* get everything by joining 
 *  + filter by category
 */
select p.*, i.file_name
from products p 
join image i on (p.id = i.p_id)
where p.category in (1,2,3)


/* get everything by joining 
* + filter by category
* + image is the one with the lowest priority
* note: selecting the priority is not necessary 
* but it's good for demonstration purposes
*/
select p.*, i.file_name, i.priority
from products p 
join image i on (p.id = i.p_id)
where p.category in (1,2,3)
group by p.id 
having i.priority = (select min(priority) from image where p_id = p.id)

答案 1 :(得分:2)

这就是答案:

select a.id, a.name, a.category, a.price, b.filename as file_name 
from products a left join (
    select i.p_id, i.filename from (select id, min(priority) as min_p 
    from images group by p_id) q 
    left join images i on q.id = i.id
) b on a.id = b.p_id 
where a.category in (1, 2, 3);

说明:

首先,您需要为每个具有最低优先级的产品设置一个集合,该产品来自此查询:

select id, min(priority) as min_p from images group by p_id;

结果将是:

+----+----------+
| id | lowest_p |
+----+----------+
|  1 |        0 |
|  2 |        2 |
|  3 |        2 |
|  4 |        1 |
+----+----------+
4 rows in set (0.00 sec)

下一步将是获得外部联接,在这种情况下,我选择(根据我的偏好任意选择),左联接:

select i.p_id, i.filename from (select id, min(priority) as min_p 
from images group by p_id) q left join images i on q.id = i.id;

此查询产生您想要的内容:

+------+----------+
| p_id | filename |
+------+----------+
|    1 | image1   |
|    2 | image3   |
|    3 | image4   |
|    4 | image7   |
+------+----------+
4 rows in set (0.00 sec)

现在你只需要再次使用左连接来装饰它:

select a.id, a.name, a.category, a.price, b.filename as file_name 
from products a left join (
    select i.p_id, i.filename from (select id, min(priority) as min_p 
    from images group by p_id) q 
    left join images i on q.id = i.id
) b on a.id = b.p_id 
where a.category in (1, 2, 3);

你会得到你想要的东西:

+------+-------+----------+-------+-----------+
| id   | name  | category | price | file_name |
+------+-------+----------+-------+-----------+
|    1 | item1 |        1 |  0.99 | image1    |
|    2 | item2 |        2 |  1.99 | image3    |
|    3 | item3 |        3 |  2.95 | image4    |
+------+-------+----------+-------+-----------+
3 rows in set (0.00 sec)

您还可以将产品放在左连接的右侧,具体取决于没有可用图像的产品时的预期。上面的查询将显示上面的视图,file_name字段为" null"。

另一方面,如果您将产品放在左侧连接的右侧,它将不会显示任何内容。

答案 2 :(得分:0)

以sarwar026的答案为基础......

SELECT p.id, name, priority, price, file_name
FROM Products p, Images i
WHERE p.id = i.p_id
  AND i.priority = (SELECT MIN(priority) FROM Images ii WHERE ii.p_id = p.id)
  AND p.category IN (1,2,3)

(在带有表副本的mysql数据库上测试)