从表中选择*,其中id在其中(从表中选择group_concat(id))如何使用group_concat函数IN IN()实现批处理和新数据?

时间:2019-06-10 10:09:04

标签: mysql

enter image description here SELECT *来自user所在的ID(从user按性别分组的group_concat(id)中选择);

我想要以下结果

UPDATE `user` SET average_age =  (SELECT AVG(score) FROM `score` WHERE id IN (select user_id from `score`))  

user WHERE ID IN(1,2,3)中选择AVG(分数); 从ID为(2,5)的user中选择AVG(分数); ......

如何使用group_concat函数IN IN()实现批处理和新数据?

数据:

  SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `score` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'man', 21, 'Tom', 300);
INSERT INTO `user` VALUES (2, 'man', 23, 'Jerry', 350);
INSERT INTO `user` VALUES (3, 'woman', 18, 'Mary', 400);
INSERT INTO `user` VALUES (4, 'woman', 12, 'Lily', 450);
INSERT INTO `user` VALUES (5, 'woman', 16, 'Jasmine', 320);
INSERT INTO `user` VALUES (6, 'woman', 16, 'Jasmine', 420);
INSERT INTO `user` VALUES (7, 'woman', 18, 'Violet', 500);
INSERT INTO `user` VALUES (8, 'woman', 18, 'Violet', 580);
INSERT INTO `user` VALUES (9, 'woman', 20, 'Sophia', 520);
INSERT INTO `user` VALUES (10, 'man', 22, 'Charlotte', 450);
INSERT INTO `user` VALUES (11, 'man', 18, 'Jackson', 400);

SET FOREIGN_KEY_CHECKS = 1;

DROP TABLE IF EXISTS `score`;
CREATE TABLE `score`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `average_score` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of score
-- ----------------------------
INSERT INTO `score` VALUES (1, '1,2,3', NULL);
INSERT INTO `score` VALUES (2, '2,5', NULL);
INSERT INTO `score` VALUES (3, '1,3,4,5', NULL);
INSERT INTO `score` VALUES (4, '2,3,6,8,11', NULL);
INSERT INTO `score` VALUES (5, '2,3,6', NULL);
INSERT INTO `score` VALUES (6, '2,3,4,5,6,7', NULL);
INSERT INTO `score` VALUES (7, '2,3,4,5,6,7', NULL);
INSERT INTO `score` VALUES (8, '3,4,5,9,10', NULL);
INSERT INTO `score` VALUES (9, '2', NULL);
INSERT INTO `score` VALUES (10, '3,5,8,9,10', NULL);
INSERT INTO `score` VALUES (11, '3,5,8,9,10', NULL);

SET FOREIGN_KEY_CHECKS = 1;

1 个答案:

答案 0 :(得分:0)

首先,我想纠正问题标题所表示的基本误解

SELECT * 
FROM user 
WHERE name IN (select group_concat(name) from user GROUP BY sex)

(我将id更改为name以更好地说明我的观点)

此查询在概念上等同于:

SELECT * 
FROM user 
WHERE name IN (
  'John,Tim,Dave',
  'Sarah,Sally,Anne'
)

这是合法语法,但几乎可以肯定不是您想要的。您不会通过提供一个字符串输入值(例如,上面用逗号分隔)来编写使用IN的查询,而是向IN提供这样的值列表:

SELECT * 
FROM user 
WHERE name IN (
  'John','Tim','Dave',
  'Sarah','Sally','Anne'
)

这是一个微妙的但从根本上来说是巨大的区别,如果您没有看到它,请给我评论

您要查询的内容应该只是要提供给IN的各个值的查询输出列表,而不是CSV字符串或CSV字符串列表。因此,您的查询应为:

SELECT * 
FROM user 
WHERE name IN (
  select name from othertable...
)

由于您的实际问题,您似乎想用另一个表的摘要数据更新一个表:

UPDATE 
  `user` u 
  INNER JOIN
  (SELECT user_id, AVG(score) avgscore FROM `score` GROUP BY user_id)  a
  ON u.id = a.user_id
SET
  u.average_age = a.avgscore

我们按人创建分数摘要,将其加入用户表并更新用户表

但是我要警告您不要这样做,因为您存储的数据可能会不同步。不用将平均值存储在用户表中,只需将数据保留在得分表中,并在每次需要时重新计算平均值:

SELECT *
FROM
  `user` u 
  INNER JOIN
  (SELECT user_id, AVG(score) avgscore FROM `score` GROUP BY user_id)  a
  ON u.id = a.user_id

这也可以写成:

SELECT u.*, AVG(s.score) as avgscore
FROM
  `user` u 
  INNER JOIN
  `score` s
  ON u.id = s.user_id
GROUP BY 
  <list of columns in u>

我倾向于避免这种模式偏向于“先在子查询中先分组,然后再连接”,因为如果您有两个表要连接并汇总第三个表,则通过导致值重复,可以更容易破坏第二个表的统计信息。相比之下,分组作为子类提供了联接,其中a中只有一行可以与b,c等中的一行匹配。哦,逐组写出分组确实很麻烦/无聊