MySQL varchar 的 AVG() 可能吗?
MySQL AVG() of varchar possible?
我正在使用 MySQL 在我大学的数据库课程中做作业。我们已经建立了一个高尔夫俱乐部的数据库,我们(除其他外)可以存储球员在不同比赛中的成绩。
现在我正在为作业编写报告,我试图证明使用 int 而不是 varchar 来存储结果更好。如果使用 int,则被取消资格的玩家将因此获得 NULL 值。如果使用了 varchar,他们将得到一个字符串:"disqualified".
我想知道的是:
- 如果使用
avg()
,MySQL会自动将varchar
转换为int
吗?
- 如果是这样,是否会大大降低数据库速度(与使用 int 相比)?
- 是否可以对字符串值进行计算?例如。如果result-attribute是一个
varchar
包含"52","68","72",是否可以计算平均值?
- 如果我得到上面列出的字符串加上一个 "disqualified" 的结果会怎样?它会像忽略 int 的 NULL 一样忽略该字符串吗?
您的问题可以通过运行简单的测试来回答:
drop table if exists golf;
create table golf(id int, int_col int, char_col varchar(50));
insert into golf(id, int_col, char_col) values
(1, 10, '10'),
(2, 20, '20');
select avg(int_col), avg(char_col) from golf;
结果:
avg(int_col) | avg(char_col)
15,0000 | 15
如您所见,VARCHAR 列上的 AVG returns 预期结果。
现在添加一行 NULL
和 'disqualified'
drop table if exists golf;
create table golf(id int, int_col int, char_col varchar(50));
insert into golf(id, int_col, char_col)values
(1, 10, '10'),
(2, 20, '20'),
(2, NULL, 'disqualified');
select avg(int_col), avg(char_col) from golf;
现在结果不同了:
avg(int_col) | avg(char_col)
15,0000 | 10
http://rextester.com/RXOQAZ69820
原因是:NULL
被AVG忽略,'disqualified'
被转换为0
,结果为(10 + 20 + 0) / 3 = 10.
要测试性能,您可以创建一个带有虚拟数据的大 table。在带有序列插件的 MariaDB 中,这可以轻松完成:
drop table if exists golf;
create table golf(id mediumint primary key, int_col smallint, char_col varchar(50));
insert into golf(id, int_col, char_col)
select seq id
, floor(rand(1)*1000) int_col
, floor(rand(1)*1000) char_col
from seq_1_to_1000000;
平均 INT:
select avg(int_col) from golf;
-- query time: 187 msec
VARCHAR 上的 AVG:
select avg(char_col) from golf;
-- query time: 203 msec
最后但同样重要的是:您不应将字符串类型用于数值。另一个原因是排序。如果您尝试对存储为字符串的数字进行排序,您将得到类似 [10, 2, 22, 3] 的结果。
您也不应该将一栏用于不同的信息类型。在您的情况下,您可以再定义一列,例如 status
,其值为 'finished' 或 'disqualified'。另一种可能的方法是使用值 0
或 1
.
的标志列 disqualified
我正在使用 MySQL 在我大学的数据库课程中做作业。我们已经建立了一个高尔夫俱乐部的数据库,我们(除其他外)可以存储球员在不同比赛中的成绩。
现在我正在为作业编写报告,我试图证明使用 int 而不是 varchar 来存储结果更好。如果使用 int,则被取消资格的玩家将因此获得 NULL 值。如果使用了 varchar,他们将得到一个字符串:"disqualified".
我想知道的是:
- 如果使用
avg()
,MySQL会自动将varchar
转换为int
吗? - 如果是这样,是否会大大降低数据库速度(与使用 int 相比)?
- 是否可以对字符串值进行计算?例如。如果result-attribute是一个
varchar
包含"52","68","72",是否可以计算平均值? - 如果我得到上面列出的字符串加上一个 "disqualified" 的结果会怎样?它会像忽略 int 的 NULL 一样忽略该字符串吗?
您的问题可以通过运行简单的测试来回答:
drop table if exists golf;
create table golf(id int, int_col int, char_col varchar(50));
insert into golf(id, int_col, char_col) values
(1, 10, '10'),
(2, 20, '20');
select avg(int_col), avg(char_col) from golf;
结果:
avg(int_col) | avg(char_col)
15,0000 | 15
如您所见,VARCHAR 列上的 AVG returns 预期结果。
现在添加一行 NULL
和 'disqualified'
drop table if exists golf;
create table golf(id int, int_col int, char_col varchar(50));
insert into golf(id, int_col, char_col)values
(1, 10, '10'),
(2, 20, '20'),
(2, NULL, 'disqualified');
select avg(int_col), avg(char_col) from golf;
现在结果不同了:
avg(int_col) | avg(char_col)
15,0000 | 10
http://rextester.com/RXOQAZ69820
原因是:NULL
被AVG忽略,'disqualified'
被转换为0
,结果为(10 + 20 + 0) / 3 = 10.
要测试性能,您可以创建一个带有虚拟数据的大 table。在带有序列插件的 MariaDB 中,这可以轻松完成:
drop table if exists golf;
create table golf(id mediumint primary key, int_col smallint, char_col varchar(50));
insert into golf(id, int_col, char_col)
select seq id
, floor(rand(1)*1000) int_col
, floor(rand(1)*1000) char_col
from seq_1_to_1000000;
平均 INT:
select avg(int_col) from golf;
-- query time: 187 msec
VARCHAR 上的 AVG:
select avg(char_col) from golf;
-- query time: 203 msec
最后但同样重要的是:您不应将字符串类型用于数值。另一个原因是排序。如果您尝试对存储为字符串的数字进行排序,您将得到类似 [10, 2, 22, 3] 的结果。
您也不应该将一栏用于不同的信息类型。在您的情况下,您可以再定义一列,例如 status
,其值为 'finished' 或 'disqualified'。另一种可能的方法是使用值 0
或 1
.
disqualified