某消费系统中包含2张表,用户信息表和消费流水表,结构和数据如下:
用户表:user
ID (自增主键) |
NAME (非空) |
Balance (非空) |
1 | A | 19.50 |
2 | A | 20.50 |
3 | B | 100.00 |
4 | C | 200.00 |
流水表:charge
ID (自增主键) |
User_id (非空) |
FEE (非空) |
Update_date |
1 | 1 | 11.00 | 2013-10-01 |
2 | 2 | 21.00 | 2013-10-05 |
3 | 3 | 31.00 | 2013-10-06 |
1)请按要求写出上面两张表的建表sql语句;
2)请分别写出下面两组sql语句的输出结果;
Delete from user;
Insert into user value (‘’, ‘D’, 300);
Truncate user;
Insert into user value (‘’, ‘D’, 300);
3)请写出能产生下面查询结果的SQL语句:
Name | Count | Balance
|
FEE |
A | 2 | 40.00 | 32.00 |
B | 1 | 100.00 | 31.00 |
C | 1 | 200.00 | 0.00 |
4)系统运行一段时间后,流水表的记录变得非常大,通过用户名(NAME)查询用户消费记录(FEE)时响应速度非常慢,请简述你的优化方案。
先建个库
CREATE DATABASE
IF NOT EXISTS mybase
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;
MySQL这样选择数据库字符集和数据库校对规则:
·如果指定了CHARACTER SET X和COLLATE Y,那么采用字符集X和校对规则Y。
·如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则。
·否则,采用服务器字符集和服务器校对规则。
如果在CREATE TABLE语句中没有指定表字符集和校对规则,则使用数据库字符集和校对规则作为默认值。
(1)
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, //对主键自动编号
`name` varchar(255) NOT NULL,
`balance` decimal(10,2) NOT NULL, //采用小数,保留两位。
PRIMARY KEY (`id`),设置主键,前面进行了自动编号的设置
KEY (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
注:此时如果我们添加数据的时候添加错了,然后我们用 delect from user where id=“?” 删除后,再添加新的数据主键自增字段不会重置 如下图:
此时我们应该使用
mysql> truncate table uses; //清空操作
接下来重新插入数据即可
INSERT INTO `user` (`name`, `balance`) VALUES ('A', 19.50);INSERT INTO `user` (`name`, `balance`) VALUES ('A', 20.50);INSERT INTO `user` (`name`, `balance`) VALUES ('B', 100.00);INSERT INTO `user` (`name`, `balance`) VALUES ('C', 200.00);
CREATE TABLE `charge` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, `fee` decimal(10,2) NOT NULL, `update_date` char(10) NOT NULL, //unsigned :非负数
PRIMARY KEY (`id`),
KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `charge` (`user_id`, `fee`, `update_date`) VALUES (1, '11.00', '2013-10-01');
INSERT INTO `charge` (`user_id`, `fee`, `update_date`) VALUES (2, '21.00', '2013-10-05');
INSERT INTO `charge` (`user_id`, `fee`, `update_date`) VALUES (3, '31.00', '2013-10-06');
输出结果
mysql> select * from user; +----+------+---------+ | id | name | balance | +----+------+---------+ | 5 | D | 300.00 | +----+------+---------+ 1 row in set (0.00 sec)
正如上面提到了新的数据主键自增字段不会重置
使用Truncate user;
再插入结果如下
mysql> select * from user; +----+------+---------+ | id | name | balance | +----+------+---------+ | 1 | D | 300.00 | +----+------+---------+ 1 row in set (0.00 sec)
3)
SELECT `name` as `Name`, COUNT(`name`) as `Count`, SUM(`balance`) as `Balance`, IFNULL(SUM(`fee`), 0.00) as `Fee` FROM `user` LEFT JOIN `charge` on `user`.`id` = `charge`.`user_id` //LEFT JOIN 左连接 以user表为基础匹配和 charge比较,找出符合 id的值等于user id的记录(条件)。 GROUP BY `name` //把满足上述过程的记录弄到一个分组里 ORDER BY `Count` DESC; // ORDER BY对结果集进行排序 asc 按升序排列 desc 按降序排列 IFNULL(SUM(`fee`), 0.00)表示如果为NULL,则设为0.00. COALESCE(SUM(`fee`), 0.00)表示合并SUM(`fee`)和0.00.
查询结果:
A 2 40.00 2.00
B 1 100.00 31.00
C 1 200.00 0.00
SELECT `name`, COUNT(`name`), SUM(`balance`), SUM(`fee`) FROM `user` INNER JOIN `charge` on `user`.`id` = `charge`.`user_id` WHERE `name` = 'A';
(4)
给user表的字段name和charge表的user_id建立索引.
如果需要外键约束user_id:
CREATE TABLE `charge_fk` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, `fee` decimal(10,2) NOT NULL, `update_date` char(10) NOT NULL, PRIMARY KEY (`id`), KEY (`user_id`), CONSTRAINT FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; INSERT INTO `charge_fk` (`user_id`, `fee`, `update_date`) VALUES (1, '11.00', '2013-10-01'); INSERT INTO `charge_fk` (`user_id`, `fee`, `update_date`) VALUES (2, '21.00', '2013-10-05'); INSERT INTO `charge_fk` (`user_id`, `fee`, `update_date`) VALUES (3, '31.00', '2013-10-06');
感谢热心的解答者 原答案作者:@eechen 感谢开源力量