什么是“一对多”元数据过滤的SQL查询?

时间:2014-07-17 18:59:27

标签: mysql sql subquery one-to-many

我已经暂时没有编写SQL了,我试图找到一个更简单的解决方案,下面的工作,但是有一个更简单,更优化的解决方案吗?

SELECT `application`.*, GROUP_CONCAT( DISTINCT `application_tags`.`tag` ) AS tags
FROM (`application`)
LEFT JOIN `application_tags` 
    ON `application_tags`.`application_id` = `application`.`id` 
WHERE NOT EXISTS (
    SELECT NULL 
    FROM `application_tags` 
    WHERE `application_tags`.`application_id` = `application`.`id`
    AND `application_tags`.`tag` = 'trashed'
)
GROUP BY `application`.`id`
ORDER BY `application`.`created` DESC
LIMIT 25

表结构如下所示:

application
    id
    name
    ...

application_tags
    application_id
    tag

我希望能够按application中设置的代码(元数据)过滤application_tags。这在尝试进行直接匹配时非常简单,例如application_tags.tag = 'trashed'

SELECT `application`.*, GROUP_CONCAT( DISTINCT `application_tags`.`tag` ) AS tags
FROM (`application`)
INNER JOIN `job` 
    ON `job`.`id` = `application`.`job_id` 
    AND job.account_id = 1
LEFT JOIN `application_tags` 
    ON `application_tags`.`application_id` = `application`.`id` 
WHERE `application_tags`.`tag` = 'trashed'
GROUP BY `application`.`id`
ORDER BY `application`.`created` DESC
LIMIT 25

但是在尝试否定搜索时却不那么容易,例如application_tags.tag != 'trashed'(考虑application_tagsapplication之间的一对多关系)

如果单个application_tags有多个application,则取消搜索无法正常工作。 trashed, read, archived等。

这可以在没有子查询的情况下完成吗? 有没有更有效的方法来做到这一点?

1 个答案:

答案 0 :(得分:0)

联接在on子句中可以有其他条件。利用它并使用内部联接作为包含属性,并使用左联接作为排除属性 表别名也可以帮助您缩短查询范围,并允许您多次包含同一个表。

SELECT a.*, GROUP_CONCAT( DISTINCT t.`tag` ) AS tags
FROM `application` a
LEFT JOIN `application_tags` t ON t.`application_id` = a.`id` -- this join is for group_concat
INNER JOIN `application_tags` t1 ON t1.`application_id` = a.`id` AND t1.`tag` = 'read' -- this join is for an included attribute
LEFT JOIN `application_tags` t2 ON t2.`application_id` = a.`id` AND t2.`tag` = 'trashed' -- this join is for an excluded attribute
WHERE t2.tag is null -- this is required to exclude all rows that matched trashed
GROUP BY a.`id`
ORDER BY a.`created` DESC

这样,您就可以将多个搜索字词组合在一起,并具有属性'和'没有属性'。

关于效率:连接的执行顺序很重要,但我不知道它们在声明中出现的顺序是否有所不同。这取决于mysql如何优化查询。