1

我有一个页面显示上传到我的系统上的文件的“文件标签”。每个文件都可以有 0、1 或多个与之关联的文件标签。

我已经成功创建了一个显示文件名及其标签的页面,例如:

File     Tag(s)
File#1   None
File#2   TAG1
File#3   TAG1, TAG2

此 SQL 查询将有助于生成上述数据:

SELECT *, GROUP_CONCAT(`ftg_name` ORDER BY `ftg_name` SEPARATOR ', ') 
  AS `x_file_tag_names` 
FROM `file` LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag` 
GROUP BY `fileftg_file` ORDER BY `file_created` DESC;

问题:

我刚刚在页面顶部实现了过滤器。过滤器允许我在系统中的不同文件标签之间进行选择。当有人选择过滤器时,我会在 WHERE 子句中添加一个条件。看看这个查询:

 SELECT *, GROUP_CONCAT(`ftg_name` ORDER BY `ftg_name` SEPARATOR ', ') 
   AS `x_file_tag_names` FROM `file` 
 LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
 LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag` 
 WHERE `fileftg_filetag` = '1' 
 GROUP BY `fileftg_file` ORDER BY `file_created` DESC;

这会在我的页面上产生这个结果:

File     Tag(s)
File#1   None
File#2   TAG1
File#3   TAG1

The problem here is that I still want it to list TAG1, TAG2 for File#3. But of course the WHERE condition is getting rid of the TAG2. I'm wondering if there is a solution that would involve only changing the SELECT condition. I was attempting to create a solution that looked something like:

SELECT *, IF(ISNULL(`filetag_file`), 'None', 
  (//a subquery that gets all file tags associated with file in outer query))
4

4 回答 4

1

One more (SQL Fiddle):

select file,
       group_concat(ftg_name order by ftg_name separator ', ') as tag_names
from file
left join link_file_filetag on fileftg_file = file_id
left join filetag on ftg_id = fileftg_filetag
where exists (select *
              from link_file_filetag 
              where fileftg_filetag = 1
                    and fileftg_file = file_id)
group by fileftg_file
order by file_created desc;

Result:

FILE   TAG_NAMES  
File#2 TAG1  
File#3 TAG1, TAG2  
于 2012-11-09T17:53:50.953 回答
0

You could do this. This is assuming there is a field called "file" in the "file" table.

SELECT  *, 
        GROUP_CONCAT(`ftg_name` ORDER BY `ftg_name` SEPARATOR ', ') AS `x_file_tag_names` 

FROM    `file` 
        LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
        LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag` 

WHERE file.file_id in (SELECT file_id 
                       FROM   `file` 
                              LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
                              LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag` 
                       WHERE `fileftg_filetag` = '1') 

GROUP BY fileftg_file ORDER BY file_created DESC;

于 2012-11-09T17:33:28.287 回答
0

This would allow you to do the group_concat as part of the select statement. I am guessing on which tables contain which fields since you did not use table prefixes in your joins.

SELECT  *, 
        (SELECT GROUP_CONCAT(`ftg_name` ORDER BY `ftg_name` SEPARATOR ', ') 
  AS `x_file_tag_names` 
         FROM `file` LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
                     LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag`
         WHERE file_id = f.file_id
         GROUP BY `fileftg_file` ORDER BY `file_created` DESC) AS tags

FROM    `file` f
        LEFT JOIN `link_file_filetag` lff ON lff.`fileftg_file` = f.`file_id` 
        LEFT JOIN `filetag` ON ft.`ftg_id` = lff.`fileftg_filetag` 

WHERE   `fileftg_filetag` = '1'
于 2012-11-09T17:48:43.643 回答
0

Sorry for all the answers, but after thinking about it, you might like this one best. This way, any group with the appropriate tag will appear. So no subquery would be needed.

 SELECT *, GROUP_CONCAT(`ftg_name` ORDER BY `ftg_name` SEPARATOR ', ') 
   AS `x_file_tag_names` FROM `file` 
 LEFT JOIN `link_file_filetag` ON `fileftg_file` = `file_id` 
 LEFT JOIN `filetag` ON `ftg_id` = `fileftg_filetag` 
 GROUP BY `fileftg_file` 
 HAVING  SUM(CASE WHEN `fileftg_filetag` = '1' THEN 1 ELSE 0 END) > 0
 ORDER BY `file_created` DESC;
于 2012-11-09T18:13:25.530 回答