【问题标题】:Try to match multiple values that are in GROUP_CONCAT尝试匹配 GROUP_CONCAT 中的多个值
【发布时间】:2012-08-04 11:13:39
【问题描述】:
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

假设用户想要所有具有选项“喝”和选项“洗澡”的对象。所以我只得到这个结果。

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

我必须如何编辑查询才能获得此结果?

【问题讨论】:

  • 你能说WHERE 'drink' in object_options AND 'bath' IN object_options吗?
  • 尝试在 WHERE 中访问时,“object_options”尚不存在

标签: sql group-concat


【解决方案1】:

最简单的: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'y 方式进行查询,不要依赖 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;

【讨论】:

  • 太好了,你成就了我的一天!非常感谢!
【解决方案2】:

另一种方法:

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 

【讨论】:

  • FIND_IN_SET 是一个严重的弯路,你可以到达 HAVING 子句中的元素 :-) 其实它有一个名字,stringly-typedprogramming
  • @MichaelBuen,我只是提供另一种方法,仅此而已。我从来没有说过这个是优越的。
猜你喜欢
  • 2016-10-21
  • 2021-06-15
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-28
相关资源
最近更新 更多