我已经暂时没有编写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_tags
与application
之间的一对多关系)
如果单个application_tags
有多个application
,则取消搜索无法正常工作。 trashed, read, archived
等。
这可以在没有子查询的情况下完成吗? 有没有更有效的方法来做到这一点?
答案 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如何优化查询。