mysql - 如何编写查询来计算具有多个约束和匹配的记录?

标签 mysql sql join

我有 5 张 table :

  1. 文件
  2. 标签
  3. join_File_Tags
  4. 个人资料
  5. join_Profile_Tags

配置文件和 join_Profile_Tags 表确定用户可以查看哪些文件。

数据可能如下所示:

  • File1 具有标签
  • 文件2具有标签
  • File3 具有标签
  • 个人资料 1 有权访问标签
  • 个人资料 2 有权访问标签

我需要一个查询来返回与配置文件标签列表中的所有标签相匹配的文件。

我想出了这个:

SELECT 
    files.id,
    files.FileName,
    (SELECT COUNT(j_file_tags.id) from j_file_tags  WHERE j_file_tags.fileID = files.id ) as fileTagCount
FROM files
LEFT JOIN j_file_tags ON j_file_tags.fileID = files.id
LEFT JOIN tags ON tags.id = j_file_tags.tagID
WHERE
    files.caseID = '123456'
    AND 
    j_file_tags.tagID IN ("One, Two, Three, Four, Five") /* i can get these before hand */
GROUP BY 
    files.id
HAVING 
    COUNT(j_file_tags.id) = fileTagCount /* this makes sure that the user has access to ALL the tags applied to the file*/

这正是我所需要的。但我现在想要得到的是:每个标签中有多少个文件?

因此,在顶部的示例数据中,Profile2 用户将看到 File1File2,但看不到 File3> 因为该标签具有 six 标签,而 profile2 无权访问该标签。我需要一个构建标签云的查询(基于 j_profile_tags 表没什么大不了的),但我需要标签包含文件计数。我需要标记 One 显示数字 2,Three 显示 1,Five 显示 1。到目前为止,我尝试的查询包括所有的计数因此,即使 Profile2 无权访问第三个文件,标签 One 的计数仍为 3。 这是我的半工作查询:

SELECT
    tags.id,
    tags.TagName,
    COUNT(tags.id) as tagCount
FROM
    tags
INNER JOIN j_file_tags ON tags.id = j_file_tags.tagID
INNER JOIN files ON j_file_tags.fileID = files.id
INNER JOIN j_profile_tags ON j_profile_tags.tagID = tags.id AND j_profile_tags.profileID = 'Profile2'
WHERE
    files.caseID = '123456'
GROUP BY
    tags.id

最佳答案

我不完全了解您的表格,尤其是“员工”列。 但如果您的意思是获取由配置文件过滤的每个标签中包含的文件数量,那么请尝试以下查询:

DECLARE @TblFiles AS TABLE(ID int identity(1, 1) primary key, TheFileName varchar(50))
DECLARE @TblTags AS TABLE(ID int identity(1, 1) primary key, TheTag varchar(50))
DECLARE @TblProfiles AS TABLE(ID int identity(1, 1) primary key, TheProfile varchar(50))

DECLARE @TblFileTagMapper AS TABLE(ID int identity(1, 1) primary key, FileID int, TagID int)
DECLARE @TblProfileTagMapper AS TABLE(ID int identity(1, 1) primary key, ProfileID int, TagID int)

INSERT INTO @TblFiles(TheFileName) VALUES ('File1'), ('File2'), ('File3')
INSERT INTO @TblTags(TheTag) VALUES ('One'), ('Two'), ('Three'), ('Four'), ('Five'), ('Six')
INSERT INTO @TblProfiles(TheProfile) VALUES ('Profile1'), ('Profile2')
INSERT INTO @TblFileTagMapper(FileID, TagID) VALUES (1,1), (1,3), (2,1), (2,5), (3,1), (3,3), (3,6)
INSERT INTO @TblProfileTagMapper(ProfileID, TagID) VALUES (1,2), (1,3), (1,4), (2,1), (2,2), (2,3), (2,4), (2,5)

--Display File-Tag
SELECT  TheFileName
       ,STUFF((SELECT ', ' + CAST(TheTag AS VARCHAR(10)) [text()]
         FROM (SELECT F.TheFileName, T.TheTag FROM @TblFileTagMapper FT INNER JOIN @TblFiles F ON FT.FileID = F.ID INNER JOIN @TblTags T ON FT.TagID = T.ID) FT 
         WHERE TheFileName = t.TheFileName
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') Tags
FROM (SELECT F.TheFileName, T.TheTag FROM @TblFileTagMapper FT INNER JOIN @TblFiles F ON FT.FileID = F.ID INNER JOIN @TblTags T ON FT.TagID = T.ID) t
GROUP BY TheFileName

--Display Profile-Tag
SELECT  TheProfile
       ,STUFF((SELECT ', ' + CAST(TheTag AS VARCHAR(10)) [text()]
         FROM (SELECT P.TheProfile, T.TheTag FROM @TblProfileTagMapper PT INNER JOIN @TblProfiles P ON PT.ProfileID = P.ID INNER JOIN @TblTags T ON PT.TagID = T.ID) PT
         WHERE TheProfile = t.TheProfile
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') Tags
FROM (SELECT P.TheProfile, T.TheTag FROM @TblProfileTagMapper PT INNER JOIN @TblProfiles P ON PT.ProfileID = P.ID INNER JOIN @TblTags T ON PT.TagID = T.ID) t
GROUP BY TheProfile

--> Param Input
DECLARE @ParamProfile VARCHAR(50) = 'Profile2'

--> The Solution Query
SELECT T.TheTag, COALESCE(X.FileCount, 0) AS NumberOfFilesWhichContainTheTag
FROM @TblTags T
LEFT JOIN(
    SELECT FT.TagID, COUNT(FT.FileID) AS FileCount
    FROM @TblFileTagMapper FT
    WHERE EXISTS(SELECT 1 FROM @TblProfileTagMapper PT INNER JOIN @TblProfiles P ON PT.ProfileID = P.ID WHERE PT.TagID = FT.TagID AND P.TheProfile = @ParamProfile)
    GROUP BY FT.TagID

) X ON T.ID = X.TagID

这些可能不是您问题的真正答案,但可能对您有所帮助。

关于mysql - 如何编写查询来计算具有多个约束和匹配的记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36463416/

相关文章:

mysql - 使用任何方法进行查询优化

sql - 仅当 NOT NULL 时加入列

mysql - pymysql|将 NULL 插入可为 null 的 int 字段

python - pip install mysql-connector 安装错误

Java 解析 Oracle 解释计划

mysql - sql请求检索每天最大,最小的第一条和最后一条记录

具有多个 WHERE 的 MYSQL 查询

php - 表单提交 PHP 代码仅在 WordPress 中损坏

sql - 如何在 T-SQL 中将 int 转换为零填充字符串?

c# - Linq to SQL 为两个不同的表两次连接到同一个表