所以我在mysql表中有一个内爆数组,基本上只是一个数字序列(例如1,5,3,1,4,5),我想知道是否有可能按平均顺序排序(或者甚至是可能的总和)表中的数字组
答案 0 :(得分:9)
不是将数字存储在分隔的字符串中,而是利用MySQL的关系功能并规范化数据:将数字存储为(key, value)
对,并将其存储在与外键相关的单独表中(即现有表的外键) )到列表中的单个数字。如果订单很重要,请添加一个附加列以指示该列表中的编号位置。
CREATE TABLE `newtable` (
`key` INT,
`value` INT,
FOREIGN KEY (`key`) REFERENCES `existingtable` (`key`)
)
然后,您只需要join个表格,GROUP BY
现有表格中的密钥以及ORDER BY
AVG()
或SUM()
个值新表;如果需要,您甚至可以使用MySQL的GROUP_CONCAT()
函数回收逗号分隔列表:
SELECT `existingtable`.*, GROUP_CONCAT(`newtable`.`value`) AS `values`
FROM `existingtable` LEFT JOIN `newtable` USING (`key`)
GROUP BY `key`
ORDER BY AVG(`newtable`.`value`) -- or use SUM() if preferred
答案 1 :(得分:1)
正如其他人所提到的,目前还不清楚你的表是什么样的,或者表中的数据是什么样的。目前还不清楚“内爆阵列”是什么样的。这是一个例子可以帮助你找到你想要的答案。
但是,让我们选择“最坏情况”,并假设你有一个包含你想要平均值的字符串。像这样:
CREATE TABLE foo (str VARCHAR(1000));
INSERT INTO foo VALUES ('1,5,3,1,4,5');
INSERT INTO foo VALUES ('2.8,4.2');
INSERT INTO foo VALUES ('bar');
INSERT INTO foo VALUES (' 0, -2, 3');
可以创建一个函数,返回“imploded array”字符串中值的平均值。举个例子:
DELIMITER $$
CREATE FUNCTION `do_average`(p_str VARCHAR(2000))
RETURNS DOUBLE
BEGIN
DECLARE c INT;
DECLARE i INT;
DECLARE s VARCHAR(2000);
DECLARE v DOUBLE;
SET c = 0;
SET v = 0;
SET s = CONCAT(p_str,',');
SET i = INSTR(s,',');
WHILE i > 0 DO
SET v = v + SUBSTR(s,1,i);
SET c = c + 1;
SET s = SUBSTR(s,i+1,2000);
SET i = INSTR(s,',');
END WHILE;
RETURN v / NULLIF(c,0);
END$$
DELIMITER ;
我们可以证明这一点:
SELECT f.str
, do_average(f.str) AS davg
FROM foo f
ORDER BY do_average(f.str)
str davg
----------- -------------------
bar 0
0, -2, 3 0.333333333333333
1,5,3,1,4,5 3.16666666666667
2.8,4.2 3.5
请注意,使用此函数,我们使用MySQL将字符串隐式转换为数字,因此空字符串或无效数字将转换为零,并且将在计算平均值时添加并计算零值
do_sum
函数几乎相同,只返回总数而不是总数除以计数。
sqlfiddle示例http://sqlfiddle.com/#!2/4391b/2/0