2016-10-14 36 views
0

我有3个表,products,productscategoriescategoriesMysql组与多列内连接

productscategories是一个多对多的表,只有其他两个表的id号。

没有GROUP BY看起来像这样的结果:

id | Url     | Category 
------------------------------------- 
1 | http://example.com/12 | hat 
2 | http://example.com/12 | shoe 
3 | http://example.com/13 | hat 
4 | http://example.com/13 | jacket 
5 | http://example.com/14 | hat 
6 | http://example.com/14 | socks 

现在我想排除的每一行与同url如果它包含任何已选定的类别,在这种情况下jacketshoe

不需要的结果是这样的:

id | Url     | Category 
------------------------------------- 
1 | http://example.com/12 | hat 
3 | http://example.com/13 | hat 
5 | http://example.com/14 | hat 

因为url id为13包括jacket我不想在那儿。 url与14相同,其中包括shoe

这是因为我有多个类别和多个不知道对方的网址。

用SQL的上述:

SELECT * FROM products 
JOIN productscategories ON products.id = productscategories.product_id 
JOIN categories ON categories.id = productscategories.category_id 
WHERE categories.slug NOT IN (
    'shoe', 
    'jacket', 
) 
GROUP BY products.image_url 

的通缉的结果:

id | Url     | Category 
------------------------------------- 
5 | http://example.com/14 | hat 

我怎样才能使一个SQL查询,使URL意识到类的,像上面?

回答

1
SELECT * FROM products 
    JOIN productscategories ON products.id = productscategories.product_id 
    JOIN categories ON categories.id = productscategories.category_id 
GROUP BY products.image_url 
HAVING sum(categories.slug IN('shoe','jacket'))=0 

categories.slug IN('shoe','jacket') - 返回1,如果在组类别或0,如果不是。 sum() - 组中鞋子/夹克的退货数量。 HAVING过滤器组与鞋/夹克在里面。

+0

这是一个奇怪的寻找答案,但它在我的测试中很有用,它也很快闪烁(比其他答案快30-60倍)。没有陷阱?谢谢! –

+1

@JensTörnell在MySQL上的工作正常。在其他RDBMS可能需要'sum(case when categories.slug IN('shoe','jacket')then 1 else 0 end)'' – Mike

1

建议1:WHERE NOT EXISTS

SELECT * FROM products 
JOIN productscategories ON products.id = productscategories.product_id 
JOIN categories ON categories.id = productscategories.category_id 
WHERE NOT EXISTS(
     SELECT 1 
     FROM products p2 
     JOIN productscategories pc2 ON p2.id = pc2.product_id 
     JOIN categories c2 ON c2.id = pc2.category_id 
     WHERE c2.slug IN ('shoe','jacket') 
     AND p2.url = products.url 
) 

建议2:OUTER JOIN

SELECT * FROM products 
JOIN productscategories ON products.id = productscategories.product_id 
JOIN categories ON categories.id = productscategories.category_id 
LEFT OUTER JOIN products p2 ON products.url = p2.url 
LEFT OUTER JOIN productscategories pc3 ON p2.id = pc2.product_id 
LEFT OUTER JOIN categories c2 ON c2.id = pc2.category_id AND c2.slug IN ('shoe','jacket') 
WHERE c2.id IS NULL 
+0

我只是想他们俩和他们的工作,但加载时间从1秒去喜欢一个半分钟。 :(你的代码中有'pc3',它应该是'pc2'. –

0

试试这个:

SELECT * FROM (
SELECT * FROM products 
JOIN productscategories ON products.id = productscategories.product_id 
JOIN categories ON categories.id = productscategories.category_id 
) AS A 
LEFT JOIN 
(
SELECT Url FROM products 
JOIN productscategories ON products.id = productscategories.product_id 
JOIN categories ON categories.id = productscategories.category_id 
WHERE Categories.slug IN ('jacket', 'shoe') 
GROUP BY url 
) B ON B.url = A.url 
WHERE B.url IS NULL