MySQL select 中的中值子查询
MySQL median subquery in select
这是我目前拥有的:
http://sqlfiddle.com/#!9/30a97c/10
架构:
CREATE TABLE IF NOT EXISTS `test` (
`t_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`t_city` varchar(64) NOT NULL,
`t_category` enum('cat1','cat2') NOT NULL,
`t_type` enum('type1','type2') NOT NULL,
`t_num` int(8) NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
INSERT INTO `test` (`t_id`, `t_city`, `t_category`, `t_type`, `t_num`) VALUES
(1, 'New York', 'cat1', 'type1', 1056),
(2, 'New York', 'cat1', 'type1', 3756),
(3, 'London', 'cat1', 'type2', 3456),
(4, 'New York', 'cat1', 'type2', 5756),
(5, 'London', 'cat1', 'type2', 3777),
(6, 'New York', 'cat2', 'type1', 3756),
(7, 'New York', 'cat2', 'type1', 3756),
(8, 'London', 'cat2', 'type1', 3777),
(9, 'New York', 'cat2', 'type2', 4556),
(10, 'Berlin', 'cat1', 'type2', 1556),
(11, 'Berlin', 'cat2', 'type2', 9756),
(12, 'London', 'cat1', 'type2', 1756);
查询:
SELECT "cat1" as st_category, "type2" as st_type, t_city as st_name,
(
SELECT (ROUND(AVG(dd.t_num) / 10) * 10) as median
FROM (
SELECT d.t_num, @rownum:=@rownum+1 as `row_number`, @total_rows:=@rownum
FROM test as d, (SELECT @rownum:=0) as r
WHERE d.t_num is NOT NULL
AND `t_category` = "cat1" AND `t_type` = "type2" AND `t_city` = "XXXXX"
ORDER BY d.t_num
) as dd
WHERE dd.row_number IN ( FLOOR((@total_rows+1)/2), FLOOR((@total_rows+2)/2) )
) as st_median,
COUNT(t_num) as st_count
FROM `test` WHERE `t_category` = "cat1" AND `t_type` = "type2"
AND t_city in ("London", "New York")
GROUP BY t_city
ORDER BY st_name ASC
我不知道用什么来代替 XXX(在子查询中),以便输出行中“t_num”的中值不为 NULL。我的 MySQL.
中没有中值函数
现在输出:
+-------------+---------+----------+-----------+----------+
| st_category | st_type | st_name | st_median | st_count |
+-------------+---------+----------+-----------+----------+
| cat1 | type2 | London | (null) | 3 |
| cat1 | type2 | New York | (null) | 1 |
+-------------+---------+----------+-----------+----------+
所需输出:
+-------------+---------+----------+-----------+----------+
| st_category | st_type | st_name | st_median | st_count |
+-------------+---------+----------+-----------+----------+
| cat1 | type2 | London | 3460 | 3 |
| cat1 | type2 | New York | 5760 | 1 |
+-------------+---------+----------+-----------+----------+
谢谢大家的帮助!这是正确的解决方案:
SET SESSION GROUP_CONCAT_MAX_LEN = 1000000;
SELECT `t_category` AS st_category,
`t_type` AS st_type,
`t_city` AS st_name,
CASE ( COUNT(*) % 2 )
WHEN 1 THEN
ROUND(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', ( COUNT(*) + 1 ) / 2), ',', -1)
/ 10) * 10
ELSE
ROUND((SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', COUNT(*) / 2), ',', -1)
+ SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', (COUNT(*) + 1) / 2), ',', -1) ) / 2
/ 10) * 10
END st_median,
COUNT(`t_num`) AS st_count
FROM `test`
WHERE `t_category` = "cat1"
AND `t_type` = "type2"
AND `t_city` IN ( "London", "New York" )
GROUP BY `t_city`
ORDER BY st_name ASC;
SQL Fiddle: http://sqlfiddle.com/#!9/30a97c/13
只有在处理大量数据时才需要 GROUP_CONCAT_MAX_LEN 设置。
在 64 位平台上最大值为 18,446,744,073,709,551,615。
在 32 位平台上:4,294,967,295。
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_group_concat_max_len
这是我目前拥有的: http://sqlfiddle.com/#!9/30a97c/10
架构:
CREATE TABLE IF NOT EXISTS `test` (
`t_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`t_city` varchar(64) NOT NULL,
`t_category` enum('cat1','cat2') NOT NULL,
`t_type` enum('type1','type2') NOT NULL,
`t_num` int(8) NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
INSERT INTO `test` (`t_id`, `t_city`, `t_category`, `t_type`, `t_num`) VALUES
(1, 'New York', 'cat1', 'type1', 1056),
(2, 'New York', 'cat1', 'type1', 3756),
(3, 'London', 'cat1', 'type2', 3456),
(4, 'New York', 'cat1', 'type2', 5756),
(5, 'London', 'cat1', 'type2', 3777),
(6, 'New York', 'cat2', 'type1', 3756),
(7, 'New York', 'cat2', 'type1', 3756),
(8, 'London', 'cat2', 'type1', 3777),
(9, 'New York', 'cat2', 'type2', 4556),
(10, 'Berlin', 'cat1', 'type2', 1556),
(11, 'Berlin', 'cat2', 'type2', 9756),
(12, 'London', 'cat1', 'type2', 1756);
查询:
SELECT "cat1" as st_category, "type2" as st_type, t_city as st_name,
(
SELECT (ROUND(AVG(dd.t_num) / 10) * 10) as median
FROM (
SELECT d.t_num, @rownum:=@rownum+1 as `row_number`, @total_rows:=@rownum
FROM test as d, (SELECT @rownum:=0) as r
WHERE d.t_num is NOT NULL
AND `t_category` = "cat1" AND `t_type` = "type2" AND `t_city` = "XXXXX"
ORDER BY d.t_num
) as dd
WHERE dd.row_number IN ( FLOOR((@total_rows+1)/2), FLOOR((@total_rows+2)/2) )
) as st_median,
COUNT(t_num) as st_count
FROM `test` WHERE `t_category` = "cat1" AND `t_type` = "type2"
AND t_city in ("London", "New York")
GROUP BY t_city
ORDER BY st_name ASC
我不知道用什么来代替 XXX(在子查询中),以便输出行中“t_num”的中值不为 NULL。我的 MySQL.
中没有中值函数现在输出:
+-------------+---------+----------+-----------+----------+
| st_category | st_type | st_name | st_median | st_count |
+-------------+---------+----------+-----------+----------+
| cat1 | type2 | London | (null) | 3 |
| cat1 | type2 | New York | (null) | 1 |
+-------------+---------+----------+-----------+----------+
所需输出:
+-------------+---------+----------+-----------+----------+
| st_category | st_type | st_name | st_median | st_count |
+-------------+---------+----------+-----------+----------+
| cat1 | type2 | London | 3460 | 3 |
| cat1 | type2 | New York | 5760 | 1 |
+-------------+---------+----------+-----------+----------+
谢谢大家的帮助!这是正确的解决方案:
SET SESSION GROUP_CONCAT_MAX_LEN = 1000000;
SELECT `t_category` AS st_category,
`t_type` AS st_type,
`t_city` AS st_name,
CASE ( COUNT(*) % 2 )
WHEN 1 THEN
ROUND(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', ( COUNT(*) + 1 ) / 2), ',', -1)
/ 10) * 10
ELSE
ROUND((SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', COUNT(*) / 2), ',', -1)
+ SUBSTRING_INDEX( SUBSTRING_INDEX( GROUP_CONCAT(`t_num`
ORDER BY `t_num` SEPARATOR ','), ',', (COUNT(*) + 1) / 2), ',', -1) ) / 2
/ 10) * 10
END st_median,
COUNT(`t_num`) AS st_count
FROM `test`
WHERE `t_category` = "cat1"
AND `t_type` = "type2"
AND `t_city` IN ( "London", "New York" )
GROUP BY `t_city`
ORDER BY st_name ASC;
SQL Fiddle: http://sqlfiddle.com/#!9/30a97c/13
只有在处理大量数据时才需要 GROUP_CONCAT_MAX_LEN 设置。 在 64 位平台上最大值为 18,446,744,073,709,551,615。 在 32 位平台上:4,294,967,295。
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_group_concat_max_len