2012-01-21 25 views
1

比方说我那里有两列的表:情绪。一行包含人名和他们的心情,如果他们有多重情绪,那么多行存储在数据库中。如何使用union语句选择mysql数据,其中数据与每个select语句匹配,即将AND运算符与UNION结合起来?

例如,在数据库是约翰,谁是幸福,兴奋,骄傲。

这被表示为

John Happy 
John Excited 
John Proud 

我想要做的就是选择被满足基于几个情绪名称。类同上联:

SELECT name WHERE mood=Happy 
UNION 
SELECT name WHERE mood=Excited 
UNION 
SELECT name WHERE mood=Proud 

但是使用上述联盟会导致:

John 
John 
John 

联盟都将导致约翰一个单一的结果,但它也将选择任何名字,仅匹配一个的查询。

我能想到这将需要每一个人mysql_result资源(我使用PHP)的几个算法,并查找匹配的结果,但我想知道的是MySQL的是否已经促进了这一点。

我意识到上述是一个相当笼统的概括,不用说我的实际程序更复杂,我已经为这个问题稍微弄虚作假,请不要犹豫提问。

回答

3

只要你有没有重复,你可以用一个子查询做到这一点:

SELECT `name` FROM (
    SELECT `name`, COUNT(*) AS `count` FROM `moods` 
    WHERE `mood` IN ('Excited', 'Happy', 'Proud') GROUP BY `name` 
) WHERE `count` = 3 

或者,您可以使用加入:

SELECT `m1`.`name` FROM `moods` `m1` 
JOIN `moods` `m2` USING (`name`) 
JOIN `moods` `m3` USING (`name`) 
WHERE `m1`.`mood` = 'Excited' AND `m2`.`mood` = 'Happy' AND `m3`.`mood` = 'Proud' 

不那么可爱,但如果使用可能会更快限制。或者可能不是。取决于查询计划者。

UPD:感谢铎康斯坦丁提醒我关于有,第一次查询就可以是:

SELECT `name` FROM `moods` 
WHERE `mood` IN ('Excited', 'Happy', 'Proud') 
GROUP BY `name` 
HAVING COUNT(*)>3 
+0

谢谢,我用了第一个,它的工作非常完美,我有一个CRON工作,每天晚上检查重复,所以不用担心。 至于更新,它不会返回任何结果,HAVING应该有什么区别? 非常感谢。 – Sam

+0

与HAVING的逻辑几乎相同,不知道是否有任何性能差异。 –

1

如果我正确理解您的问题,我认为在这种情况下,您实际上并不需要UNION,而只需要WHERE声明中的多个条件。

试试这个:

SELECT name, mood FROM myTable WHERE mood in ('Happy','Excited','Proud') 

应该给出结果:

John, Happy 
John, Excited 
John, Proud 

如果你不关心怎样的心情多个结果,试试这个:

SELECT DISTINCT name FROM myTable WHERE mood in ('Happy','Excited','Proud') 

这只是给:

应该给出结果:

John 

更新 如果你想符合的所有条件,你可能不得不使用子查询:

SELECT DISTINCT name FROM myTable 
WHERE name IN 
    (SELECT name FROM myTable WHERE mood = 'Happy') 
AND name IN 
    (SELECT name FROM myTable WHERE mood = 'Excited') 
AND name IN 
    (SELECT name FROM myTable WHERE mood = 'Proud') 
+0

保罗,谢谢你的回应,非常感谢。 使用SELECT DISTINCT似乎没有带来任何结果,因为您的第一个解决方案确实带来了所有结果。 – Sam

+0

难道这不会返回至少有一种心情相匹配的所有名字吗(不是全部三种)? –

+0

只是再次尝试,实际上使用DISTINCT带来的结果,但他们不符合每个条件,即其他人只是快乐返回。 AND运算符能否以某种方式应用于您的解决方案? – Sam

0

替换与UNION INTERSECT。

+0

在MySQL –

+0

中没有'INTERSECT'这会工作(在带有INTERSECT的SQL中),但似乎效率低下,实际上使用3个选择来实现使用一个选项可以完成的功能* –

1

尝试用:

SELECT name FROM user_moods um1 
    INNER JOIN user_moods um2 ON um1.name = um2.name 
WHERE um1.mood IN ('Happy','Excited','Proud') 
GROUP BY um2.mood 
HAVING COUNT(um2.mood) = 3 # the number of different moods 
+0

不错,我忘了HAVING,但为什么额外加入?另外,MySQL手册指出“例如,HAVING子句必须位于任何GROUP BY子句之后,并且位于任何ORDER BY子句之前。” –

1

您的查询已经是正确的。您可以ADD使用您在WHERE子句中搜索到的字添加一列。

SELECT name,'Happy' as imood WHERE mood='Happy' 
    UNION 
SELECT name,'Excited' as imood WHERE mood='Excited' 
    UNION 
SELECT name,'Proud' as imood WHERE mood='Proud' 
+0

非常感谢您的回答非常感谢。问题是这个返回的人只是完成了一个select语句,而不是所有的人。 – Sam

相关问题