尝试匹配GROUP_CONCAT中的多个值

时间:2012-08-07 12:26:25

标签: sql group-concat

options_table

options_id    | object_id  |   option_value
=========================================
1            |    1       |    drink
2            |    2       |    ice
3            |    1       |    bath
4            |    2       |    soda
5            |    2       |    drink
6            |    3       |    ice
7            |    4       |    bath
8            |    2       |    bath
9            |    1       |    storm


object_table

object_id    |   object_name
=============================
1            |    sun
2            |    moon
3            |    mars
4            |    jupiter

查询

SELECT object_table.object_name GROUP_CONCAT(options_table.option_value ) as object_options 
FROM options_table
LEFT JOIN object_table
ON object_table.object_id = options_table.object_id    
GROUP BY options_table.object_id

所以我得到了像

这样的结果
object_name | object_options
=========================================
moon        | ice, soda, drink, bath
sun         | drink, bath, storm
mars        | ice
jupiter     | bath

让我们说用户想要所有具有选项“drink”和“bath”选项的对象。所以我只得到这个结果。

object_name | object_options
=========================================
moon        | ice, soda, drink, bath
sun         | drink, bath, storm

如何编辑查询以获得此结果?

2 个答案:

答案 0 :(得分:4)

最简单的:http://www.sqlfiddle.com/#!2/1b2e3/5

select obj.object_name, 
    group_concat(opt.option_value order by opt.options_id) as object_options
from options_table opt
join object_table obj using(object_id)
group by obj.object_id
having sum(opt.option_value in ('drink','bath')) = 2
order by obj.object_name;

输出:

| OBJECT_NAME |      OBJECT_OPTIONS |
-------------------------------------
|        moon | ice,soda,drink,bath |
|         sun |    drink,bath,storm |

如果你想要更多的ANSI-SQL方法来进行查询,不要依赖于MySQLism(布尔/整数二元性),而是在SUM上使用显式值:http://www.sqlfiddle.com/#!1/14cf4/1

select obj.object_name, 
    array_agg(opt.option_value order by opt.options_id) as object_options
from options_table opt
join object_table obj using(object_id)
group by obj.object_id, obj.object_name
having sum(case when opt.option_value in ('drink','bath') then 1 end) = 2
order by obj.object_name;

答案 1 :(得分:0)

另一种方法:

SELECT object_name, object_options FROM   
  (SELECT object_table.object_name, 
          GROUP_CONCAT(options_table.option_value ) as object_options
   FROM options_table
   LEFT JOIN object_table
     ON object_table.object_id = options_table.object_id    
   GROUP BY options_table.object_id) t   
WHERE FIND_IN_SET('drink', object_options)> 0 AND  FIND_IN_SET('bath', object_options)> 0