GROUP_CONCAT和INNER JOIN与WHERE子句

时间:2014-03-06 20:17:34

标签: mysql sql

我遇到了获取数据的问题。我想找到所有课程,其中包含where子句中的标志,并获得它包含的所有标志课程。

课程表的记录:

+----+----------+
| id |   name   |
+----+----------+
| 1  | Spring   |
| 2  | Hibernate|
| 3  | C#       |
+----+----------+

course_flags 表的记录:

+----+----------+----------+
| id |course_id |  flag_id |
+----+----------+----------+
| 1  |     1    |     1    |
| 2  |     1    |     2    |
| 3  |     2    |     1    |
+----+----------+----------+

标志表的记录:

+----+------------+
| id |    name    |
+----+------------+
| 1  | promocja   |
| 2  |last minute |
+----+------------+

我的查询

SELECT course.id, course.name,
       GROUP_CONCAT(Flag.id SEPARATOR ',') as flags
FROM course
INNER JOIN course_flags ON 
    course.id = course_flags.course_id
INNER JOIN flag ON 
    flag.id = course_flags.flag_id
WHERE flag.name LIKE 'promocja'
GROUP BY Course.id

不幸的是,我的数据库引擎在 flags 列中返回了带有一个标记的记录:

+----+----------+----------+
| id |   name   |   flags  |
+----+----------+----------+
| 1  | Spring   |     1    |
| 2  | Hibernate|     1    |
+----+----------+----------+

我原本希望得到这个结果:

+----+----------+----------+
| id |   name   |   flags  |
+----+----------+----------+
| 1  | Spring   |   1,2    |
| 2  | Hibernate|    1     |
+----+----------+----------+

问我怎么得到它?

提前致谢!

2 个答案:

答案 0 :(得分:2)

WHERE子句将记录之前的限制为分组;而HAVING子句在分组后限制结果

SELECT   course.id, course.name, GROUP_CONCAT(Flag.id) flags
FROM     course
    JOIN course_flags ON course_flags.course_id = course.id
    JOIN flag ON flag.id = course_flags.flag_id
GROUP BY Course.id
HAVING   SUM(flag.name = 'promocja')

sqlfiddle上查看。

答案 1 :(得分:2)

简单地使用这样的连接的问题是你的WHERE子句将减少结果集可用的标志。你真正需要做的是使用一个子选择来首先确定具有这个标志的id,然后使用那组id,确定每个id的标志。可能看起来像这样:

SELECT
    c.id AS id,
    c.name AS name,
    GROUP_CONCAT(cf.flag_id) AS flags
FROM course AS c
INNER JOIN course_flag AS cf
    ON c.id = cf.course_id
INNER JOIN 
    (SELECT cf2.course_id AS id
    FROM course_flags AS cf2
    INNER JOIN flag AS f
    WHERE f.name = ?) AS ids
    ON c.id = ids.id
GROUP BY c.id

?是您要查询的标志名称。注意我在=子句中使用了WHERE而不是LIKE,因为您甚至没有使用LIKE功能(您没有通配符)。