我有一个表订单:
|--------------------|-----------------|------------|
| user_id | article_id | Name |
|--------------------|-----------------|------------|
| 1 | 39 | John |
| 1 | 39 | John |
| 2 | 39 | Mike |
| 2 | 19 | Mike |
| 3 | 39 | Dave |
|--------------------|-----------------|------------|
如何只选择具有article_id = 39的用户,无论多少次,但是只发生一次。 我需要选择用户John和用户Dave,但不要选择Mike。 Mike有article_id 39,但他也有article_id = 19。 该查询应该返回用户John和Dave。
我试过这个问题:
SELECT * FROM orders AS o where o.article_id = 39
GROUP BY o.user_id HAVING COUNT(o.article_id) > 0
但它返回所有三个用户。我不需要用户Mike。
答案 0 :(得分:6)
在HAVING
子句中使用条件聚合:
SELECT user_id, Name
FROM orders
GROUP BY user_id, Name
HAVING SUM(CASE WHEN article_id <> 39 THEN 1 ELSE 0 END) = 0;
注意:您的表未规范化,用户信息属于单独的用户表。我可以通过在GROUP BY
子句中包含名称来解决这个问题,但理所当然我们应该通过user_id
聚合。
答案 1 :(得分:3)
首先,您选择所有没有article_id 39的用户:
SELECT user_id FROM orders WHERE article_id <> 39
然后选择article_id为39且不在此列表中的用户。总的来说,查询将是:
SELECT user_id FROM orders WHERE article_id = 39
AND user_id NOT IN (SELECT user_id from orders where article_id <> 39)
再次,蒂姆和约翰已经发布的答案更有效,更好。我只是在学习SQL时发现这样的查询更易于阅读/理解。
答案 2 :(得分:1)
另一种方法是使用MIN()
和MAX()
SELECT user_id
FROM orders
GROUP BY Name
HAVING MIN(article_id) = MAX(article_id)
AND MIN(article_id) = 39