2016-04-19 20 views
1

我有5個表如下:經與在SELECT語句中得到一個計數問題

  • 文件
  • 標籤
  • 型材
  • j_file_tags
  • j_profile_tags

所以文件可以有標籤,配置文件可以訪問某些標籤。

我放在一起的兩個查詢是執行以下操作:

  1. 得到的文件列表特定的配置文件訪問(配置文件必須能訪問所有標籤文件可能有)
  2. GET該配置文件有權訪問的標籤列表以及該標籤中至少有一個文件的位置。

我需要查詢2的是一個標籤中有多少文件的計數。

這裏的表結構和樣本數據:

CREATE TABLE `files` (
`id` int(4) NOT NULL AUTO_INCREMENT , 
`fileName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 
`empID` int(4) NOT NULL , 
PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci 
ROW_FORMAT=Dynamic; 

CREATE TABLE `j_file_tags` (
`id` int(4) NOT NULL AUTO_INCREMENT , 
`fileID` int(4) NULL DEFAULT NULL , 
`tagID` int(4) NULL DEFAULT NULL , 
PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci 
ROW_FORMAT=Dynamic; 

CREATE TABLE `j_profile_tags` (
`id` int(4) NOT NULL AUTO_INCREMENT , 
`profileID` int(4) NULL DEFAULT NULL , 
`tagID` int(4) NULL DEFAULT NULL , 
PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci 
ROW_FORMAT=Dynamic; 

CREATE TABLE `profiles` (
`id` int(4) NOT NULL AUTO_INCREMENT , 
`profileName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , 
PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci 
ROW_FORMAT=Dynamic; 

CREATE TABLE `tags` (
`id` int(4) NOT NULL AUTO_INCREMENT , 
`tagName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , 
PRIMARY KEY (`id`) 
) 
ENGINE=InnoDB 
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci 
ROW_FORMAT=Dynamic; 

INSERT INTO `files` VALUES ('1', 'FileOne', '1'); 
INSERT INTO `files` VALUES ('2', 'FileTwo', '1'); 
INSERT INTO `files` VALUES ('3', 'FileThree', '1'); 
INSERT INTO `files` VALUES ('4', 'FileFour', '2'); 
INSERT INTO `files` VALUES ('5', 'FileFive', '2'); 
INSERT INTO `files` VALUES ('6', 'FileSix', '2'); 
INSERT INTO `files` VALUES ('7', 'FileSeven', '2'); 

INSERT INTO `profiles` VALUES ('1', 'ProfileOne'); 
INSERT INTO `profiles` VALUES ('2', 'ProfileTwo'); 
INSERT INTO `profiles` VALUES ('3', 'ProfileThree'); 

INSERT INTO `tags` VALUES ('1', 'TagOne'); 
INSERT INTO `tags` VALUES ('2', 'TagTwo'); 
INSERT INTO `tags` VALUES ('3', 'TagThree'); 
INSERT INTO `tags` VALUES ('4', 'TagFour'); 
INSERT INTO `tags` VALUES ('5', 'TagFive'); 

INSERT INTO `j_file_tags` VALUES ('1', '1', '1'); 
INSERT INTO `j_file_tags` VALUES ('2', '1', '3'); 
INSERT INTO `j_file_tags` VALUES ('3', '2', '1'); 
INSERT INTO `j_file_tags` VALUES ('4', '2', '5'); 
INSERT INTO `j_file_tags` VALUES ('5', '3', '1'); 
INSERT INTO `j_file_tags` VALUES ('6', '3', '3'); 
INSERT INTO `j_file_tags` VALUES ('7', '3', '6'); 
INSERT INTO `j_file_tags` VALUES ('8', '2', '3'); 
INSERT INTO `j_file_tags` VALUES ('9', '4', '1'); 
INSERT INTO `j_file_tags` VALUES ('10', '4', '2'); 
INSERT INTO `j_file_tags` VALUES ('11', '5', '1'); 
INSERT INTO `j_file_tags` VALUES ('12', '5', '6'); 

INSERT INTO `j_profile_tags` VALUES ('1', '1', '2'); 
INSERT INTO `j_profile_tags` VALUES ('2', '1', '3'); 
INSERT INTO `j_profile_tags` VALUES ('3', '1', '4'); 
INSERT INTO `j_profile_tags` VALUES ('4', '2', '1'); 
INSERT INTO `j_profile_tags` VALUES ('5', '2', '2'); 
INSERT INTO `j_profile_tags` VALUES ('6', '2', '3'); 
INSERT INTO `j_profile_tags` VALUES ('7', '2', '4'); 
INSERT INTO `j_profile_tags` VALUES ('8', '2', '5'); 
INSERT INTO `j_profile_tags` VALUES ('9', '1', '1'); 
INSERT INTO `j_profile_tags` VALUES ('10', '1', '5'); 

這裏是我的2個查詢:

/* Get list of files: limit by specific employee AND by tags the use has access to */ 
SELECT 
    `files`.`id`, 
    `files`.`fileName`, 
    `files`.`empID`, 
    GROUP_CONCAT(CONCAT(`tags`.`id`) SEPARATOR ', ') as `FileTags` 
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`.`empID` = 1 
    AND 
    `j_file_tags`.`tagID` IN (1,2,3,4,5) 
GROUP BY 
    `files`.`id` 
HAVING 
    COUNT(`j_file_tags`.`id`) = (SELECT COUNT(`j_file_tags`.`id`) FROM `j_file_tags` WHERE `j_file_tags`.`fileID` = `files`.`id`); 

/* SECOND QUERY where i need help */ 
SELECT 
    `tags`.`id`, 
    `tags`.`tagName`, 
    '1' as `fileCount` /* i need this to be an actual count */ 
FROM 
    `tags` 
LEFT JOIN `j_file_tags` ON `j_file_tags`.`tagID` = `tags`.`id` 
LEFT JOIN `files` ON `files`.`id` = `j_file_tags`.`fileID` 
LEFT JOIN `j_profile_tags` ON `j_profile_tags`.`tagID` = `tags`.`id` 
WHERE 
    `j_profile_tags`.`profileID` = 1 
    AND 
    `files`.`empID` = 1 
GROUP BY 
    `tags`.`id`; 
/* the fileCount column would need to say for TagOne - 2, for TagThree - 2 and for TagFive - 1 */ 

在樣本數據中的第一個查詢返回:

  • | 1 | FileOne | 1 | 1,3
  • | 2 | FileTwo | 1 | 3,1,5

第二查詢返回:

  • | 1 | TagOne |應該返回2
  • | 3 | TagThree |應該返回2
  • | 5 | TagFive | |應該返回1
+0

除非我遺漏了一些東西,否則你的問題很簡單:_ **我需要查詢2的是一個標籤中有多少文件的計數** _問題是我看到的結果不是你的期望是什麼:對於Tag1,Tag3,Tag5,我分別計算'3,3,1',你期望'2,2,1' ...爲什麼?請澄清[SQL小提琴](http://sqlfiddle.com/#!9/eb659/18) –

+0

是的,我期待2,2,1,因爲第一個查詢是做什麼的。基本上,權限。總體而言,對於該員工,有3,3,1個文件,但由於我的個人資料,我可以訪問更少的文件。第一個查詢返回2個文件,因爲這是我可以訪問的內容,爲了說明的目的,我將相關的標記ID連接起來。所以我需要計算這個上下文中的文件而不是文件表中的所有文件。 –

+0

因此,如果我創建一個標籤雲,它會說TagOne(2),TagThree(2),TagFive(1),然後從那裏用戶可以單擊「TagThree」,只是看到這些文件。如果標籤雲說TagThree(3),並且他們點擊它並且只能看到2個文件,那將會令人困惑。 –

回答

0

答案其實很簡單,你在第一個查詢有HAVING子句是因爲有真正的3個文件與標籤1和3。我建議一起取出全部或找出擺脫你的結果另一種方式來做到這一點。我在下面重寫了您的查詢以顯示您想要的結果,但它不是一個修復所有。

選擇 tagsidtagstagName, count(fileID)as'fileCount' FROM files LEFT JOIN j_file_tags ON j_file_tagsfileID = filesid LEFT JOIN tags ON tagsid = j_file_tagstagID 其中 filesempID = 1 AND j_file_tagstagID IN(1,2,3,4,5) AND fileID IN(1,2) GROUP BY tagsid

+0

這似乎工作,但你正在通過ID特別呼叫這兩個文件。所以我想我需要運行我的第一個查詢裏面的「in」語句。不知道可能有多高效。 –

+0

「擁有」條款的原因是爲了獲得文件可能具有的所有標籤的完全匹配。我不相信有這方面的工作。如果fileTwo具有標籤1,3,5,我必須確保配置文件可以訪問所有三個標籤,而不僅僅是1,3,5個標籤中的一個或兩個。 –

+0

我很困惑你爲什麼要從你在having子句中創建的子查詢的文件表中調用一個變量,例如id?有另一種方法來檢查這個嗎? –