我必须用 3 个表来建立与文件和类别的一对多关系,我的表架构如下所示:
类别表
CREATE TABLE `categories` (
`id` INT(3) NOT NULL AUTO_INCREMENT,
`category_name` VARCHAR(25) NOT NULL,
`visible_name` VARCHAR(25) NOT NULL,
`is_active` TINYINT(1) NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_file_category_visible_name_colum` (`visible_name`)
)
ENGINE = INNODB;
文件表
CREATE TABLE `files` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NOT NULL,
`filename` VARCHAR(255) NOT NULL,
`description` TEXT NOT NULL,
`date_uploaded` BIGINT(20) DEFAULT 0,
`last_updated` BIGINT(20) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_unique_file` (`filename`)
)
ENGINE = INNODB;
file_categories 表
CREATE TABLE `file_categories` (
`fkfile` BIGINT(20) NOT NULL,
`fkcategory` INT(3) NOT NULL,
PRIMARY KEY (`fkfile`, `fkcategory`),
FOREIGN KEY (`fkfile`)
REFERENCES files (`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT,
FOREIGN KEY (`fkcategory`)
REFERENCES categories (`id`)
ON UPDATE CASCADE
ON DELETE RESTRICT
)
ENGINE = INNODB;
以下是我测试的示例数据:
INSERT INTO `stackoverflow_qst`.`files` (`id`, `title`, `filename`, `description`, `date_uploaded`, `last_updated`) VALUES (NULL, 'First Dummy File', 'fdf.pdf', 'Just a dummy file', '1552295385043', '0');
INSERT INTO `stackoverflow_qst`.`categories` (`id`, `category_name`, `visible_name`, `is_active`) VALUES (NULL, 'Category 1', 'Category One', '1'), (NULL, 'Category 2', 'Category Two', '2'), (NULL, 'Category 3', 'Category Three', '1');
INSERT INTO `stackoverflow_qst`.`file_categories` (`fkfile`, `fkcategory`) VALUES ('1', '1'), ('1', '2'), ('1', '3');
在选择文件时,我希望选择该文件的所有类别 ID 作为逗号分隔的列,文件我的选择查询如下所示:
SELECT f.id, f.title, f.filename, f.description, f.date_uploaded, f.last_updated,
GROUP_CONCAT(DISTINCT fc.fkcategory ORDER BY fc.fkcategory ASC ) AS categories_ids
FROM `files` AS f
INNER JOIN `file_categories` AS fc ON (fc.fkfile = f.id)
GROUP BY fc.fkfile
它正确返回其他列,但 categories_ids 列除外,该列返回预览时出现错误的 BLOB,如以下屏幕截图所示: categories_ids column BLOB preview Query Result in PHPMyAdmin
我已经继续以逗号分隔的方式查询 file_categories 表,但它仍然像往常一样返回一个 blob。我在 StackOverflow 上查找了相关问题,我的查询似乎没问题,我的一些查找是: MySQL : Multiple row as comma separated single row (这里的回答很直接甚至指向MySql Doc), MYSQL comma separated IDs vs separate table , 和 SQL Join multiple ids comma separated但我仍然遇到同样的问题,是否与我使用的 MySql 版本有关?
当前 MySql 版本 5.1.41,严格用于部署我当前项目的服务器。
最佳答案
编辑:
想通了。 GROUP_CONCAT
需要一个字符串。通常返回 TEXT
或 BLOB
类型。考虑到您的数据是 INT
类型,MySQL 似乎选择了 BLOB
。要返回 TEXT
,您需要先将整数值转换/转换为字符值。
GROUP_CONCAT
引用:https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
试试这个:
SELECT
f.id,
f.title,
f.filename,
f.description,
f.date_uploaded,
f.last_updated,
GROUP_CONCAT(DISTINCT CONVERT(fc.fkcategory, char(8)) ORDER BY fc.fkcategory ASC ) AS categories_ids
FROM `files` AS f
INNER JOIN `file_categories` AS fc ON (fc.fkfile = f.id)
GROUP BY
f.id,
f.title,
f.filename,
f.description,
f.date_uploaded,
f.last_updated
您应该仍然升级您的 MySQL 版本。在那里的某个地方,软件安全天使正为将应用程序部署在古老的数据库版本上的前景而大声疾呼。想想软件安全天使。不要让他们哭。
旧答案:
您真的应该从 MySQL 5.1 升级。使用这样的旧版本会使您极易受到安全问题的影响,而且您会错过更高版本的优秀功能。
好吧,现在开始我的演讲吧。
在 MySQL 5.6 上测试,您的查询运行成功返回数据;然而,正如 Panagiotis Kanavos 所提到的,你真的应该指定你的非聚合字段(读作,字段不使用聚合函数,如 MAX()
,AVG()
, COUNT()
等)在 GROUP BY
子句中。
看这个例子
SELECT
f.id,
f.title,
f.filename,
f.description,
f.date_uploaded,
f.last_updated,
GROUP_CONCAT(DISTINCT fc.fkcategory ORDER BY fc.fkcategory ASC ) AS categories_ids
FROM `files` AS f
INNER JOIN `file_categories` AS fc ON (fc.fkfile = f.id)
GROUP BY
f.id,
f.title,
f.filename,
f.description,
f.date_uploaded,
f.last_updated
你的版本和这个版本都可以运行,不过我强烈推荐这个版本。不指定组中的非聚合字段会产生不确定的结果。您不能保证将返回的数据是一致的。
我没有可用于测试的 5.1 实例,因此我无法重现您的错误。对于您所看到的行为,我也没有任何解释。我能提供的最好方法是尝试修复您的查询以使用 GROUP BY
并查看是否可以解决问题。这不一定能解决问题,但值得一试。
这是一个有趣的 SQL fiddle :http://sqlfiddle.com/#!9/1eb5fd/3
关于MySQL GROUP_CONCAT 返回带有空结果错误的 BLOB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55116657/