跨多行的MySQL条件语句

时间:2019-03-21 16:21:09

标签: mysql

我有一个这样的个人资料表

|--------|-----------|
| People | Favorite  |
|--------|-----------|
|   A    |   Movie   |
|   B    |   Movie   |
|   B    |  Jogging  |
|--------|-----------|

问:如何找回最喜欢电影而不是慢跑的人?

在此表中,结果仅为人物A。

尽管我想到了这个

select People from Profile
where
People
in
(select People from Profile
where favorite='Movie')
and
People
not in
(select People from Profile
where favorite='Jogging')

但是,任何建议或答案(不使用join或union子句)似乎都可以更好?

5 个答案:

答案 0 :(得分:2)

https://www.db-fiddle.com/f/rboiDpxxbABCpjtduEz7uY/1

SELECT People 
FROM `profile`
GROUP BY people
HAVING SUM('Movie' = favorite) > 0
   AND SUM('Jogging' = favorite) = 0

答案 1 :(得分:1)

有很多方法。虽然可以使用UNION,但它相当混乱且效率低下。 MySQL没有MINUS子句,该子句可以使查询相当容易理解。

您可以汇总数据:

SELECT people
, MAX(IF(favorite='jogging', 1, 0)) as jogging
, MAX(IF(favorite='movie', 1, 0)) as movie
FROM profile
GROUP BY people
HAVING movie=1 AND jogging=0

或使用外部联接:

SELECT m.people
FROM profile m
LEFT JOIN
 ( SELECT j.people
 FROM joggers j
 WHERE j.favorite='jogging' ) joggers
ON m.people=joggers.people
WHERE joggers.people IS NULL
AND m.favorite='movies'

使用NOT IN / NOT EXISTS可以使语法更清晰,但效率仍然很低。

答案 2 :(得分:0)

有几种查询模式将返回满足规范的结果。

我们可以将NOT EXISTS与相关子查询一起使用:

SELECT p.people 
  FROM profile p 
 WHERE p.favorite = 'Movie' 
   AND NOT EXISTS ( SELECT 1
                      FROM profile q
                     WHERE q.favorite = 'Jogging' 
                       AND q.people   = p.people   /* related to row in out query */
                  )
 ORDER
    BY p.people 

等效的结果也可以通过 anti-join 模式完成:

SELECT p.people 
  FROM profile p
  LEFT
  JOIN profile q
    ON q.people   = p.people
   AND q.favorite = 'Jogging'
 WHERE q.people IS NULL
   AND p.favorite = 'Movie'
 ORDER BY p.people 

另一种选择是条件聚合。无法保证唯一性和一些MySQL速记:

SELECT p.people
  FROM profile p
 GROUP
    BY p.people
HAVING 1 = MAX(p.favorite='Movie')
   AND 0 = MAX(p.favorite='Jogging')

用于条件聚合的更具可移植性,更符合ANSI标准的语法:

SELECT p.people
  FROM profile p
 GROUP
    BY p.people
HAVING 1 = MAX(CASE p.favorite WHEN 'Movie'  THEN 1 ELSE 0 END)
   AND 0 = MAX(CASE p.favorite WHEN Jogging' THEN 1 ELSE 0 END)

答案 3 :(得分:0)

当您要在同一列中具有多个条件时,这是一个常见问题。我已经回答了here,并且还有其他方法,例如相交和子查询。

SELECT people, GROUP_CONCAT(favorite) as fav
FROM profile
GROUP BY people
HAVING fav REGEXP 'Movie'
AND NOT fav REGEXP 'Jogging';

答案 4 :(得分:0)

使用group by people并检查favorite的最小值和最大值为'Movie'

select people from tablename
where favorite in ('Movie', 'Jogging')
group by people
having min(favorite) = 'Movie' and max(favorite) = 'Movie'