2012-05-19 3 views
0

У меня есть две таблицы:Соединение двух таблиц MySQL, но с дополнительными условиями?

Продукты:

+-------------------------------------------------+ 
| 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.

Любая помощь была бы принята с благодарностью!

ответ

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».

С другой стороны, он не отображает изображения, если вы поместите продукты с правой стороны влево.

4

Я добавлю пошаговое руководство, сначала получая право на соединение, , затем добавив некоторые условия для фильтрации категории и, наконец, группируя и используя предложение having с подвыборкой. Вам необходимо будет использовать последний код в вашем коде. Я также тестировал это на экземпляре mysql, и он работает. Я использую группу на случай, если вам понадобится другой сложный материал. Приятно иметь пример. Синтаксис является 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) 
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 с копиями таблиц)

Смежные вопросы