MySQL: condition on result of GROUP_CONCAT?

懵懂的女人 提交于 2019-12-13 01:50:45

问题


I have an SQL setup akin to the following:

ARTICLES

  • id (PK)
  • name

TAGS

  • id (PK)
  • tag

...and a third table logging associations between the two, since there can be multiple tags to each article:

ARTICLE_TAG_ASSOCS

  • id (PK)
  • article_id (FK)
  • tag_id (FK)

Question: how to find articles that have a particular tag?

The best I could come up with was this:

SELECT
    name, GROUP_CONCAT(CASE WHEN tag = 'some-tag' THEN tag ELSE NULL END) AS tags
FROM
    articles, tags, article_tag_assocs
WHERE
    articles.id = article_id && tags.id = tag_id && tags IS NOT NULL
GROUP BY
    article_id

That's on the right lines; if an article doesn't have the tag "some-tag" then that column shows up with a null value in the "tags" column. But how can I eliminate that row completely?

Naturally, I tried appending

&& tags NOT LIKE '%some-tag%'

...to my WHERE clause, before learning that you can't use GROUP_CONCAT aliases in WHERE clauses. So I tried appending:

HAVING tags IS NOT NULL;

...to the query, with the same result, i.e. MySQL says it doesn't recognise the column "tags".

Any help appreciated.


回答1:


How about this?

SELECT distinct a.name
FROM articles a join
     article_tag_assocs ata
     on a.id = ata.article_id join
     tags t
     on t.id = ata.tag_id
WHERE t.tag = 'some-tag';

It answers your question quite directly.

Note that this also introduces table aliases. These make the query easier to write and to read.




回答2:


Although I don't fully understand your data requirement, GROUP_CONCAT doesn't seem like it is what you really want based on the information you have given.

But anywhoo.. perhaps you could use a subquery?

SELECT * FROM (
    SELECT
        name, GROUP_CONCAT(CASE WHEN tag = 'some-tag' THEN tag ELSE NULL END) AS tags
    FROM
        articles, tags, article_tag_assocs
    WHERE
        articles.id = article_id && tags.id = tag_id && tags IS NOT NULL
    GROUP BY
        article_id
) A where a.tags is not null

Or a HAVING:

    SELECT
        name, GROUP_CONCAT(CASE WHEN tag = 'some-tag' THEN tag ELSE NULL END) AS tags
    FROM
        articles, tags, article_tag_assocs
    WHERE
        articles.id = article_id && tags.id = tag_id && tags IS NOT NULL
    GROUP BY
        article_id
    HAVING
        GROUP_CONCAT(CASE WHEN tag = 'some-tag' THEN tag ELSE NULL END) IS NOT NULL



回答3:


  1. Use proper joins (the syntax is 25 years old now).
  2. Use straightforward conditions without CASE etc.
  3. Add an extra join to tags just for the target tag.

I assume that you want all tags, but at least one must be some-tag

SELECT name, GROUP_CONCAT(distinct t1.tag) AS tags
FROM articles
JOIN article_tag_assocs ON articles.id = article_id
JOIN tags t1 ON t1.id = tag_id
JOIN tags t2 ON t2.id = tag_id AND t2.tag = 'some-tag'
GROUP BY name


来源:https://stackoverflow.com/questions/24499765/mysql-condition-on-result-of-group-concat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!