2017-03-03 2 views
-1

Je fais une affectation dans un cours de base de données sur mon uni en utilisant MySQL. Nous avons créé une base de données d'un club de golf, où nous (entre autres) pouvons stocker les résultats des joueurs de différents jeux.MySQL AVG() de varchar possible?

Maintenant, j'écris le rapport pour l'affectation, et j'essaie de prouver qu'il est préférable d'utiliser un int plutôt qu'un varchar pour stocker les résultats. Si un int est utilisé, les joueurs disqualifiés obtiendront une valeur NULL en conséquence. Si un varchar aurait été utilisé, ils auraient une chaîne: "disqualifié".

Les choses que je me demande sont:

  1. Est-ce que MySQL convertit automatiquement varchar à int si avg() est utilisé (par exemple) lorsqu'un calcul est sur le point de se produire?
  2. Si c'est le cas, cela ralentit-il beaucoup la base de données (par rapport à si un int aurait été utilisé)?
  3. Est-il possible de faire des calculs sur des valeurs de chaîne? Par exemple. si l'attribut résultat est un varchar contenant "52", "68", "72", la moyenne peut-elle être calculée?
  4. Que se passera-t-il si j'ai les chaînes listées ci-dessus plus un résultat qui est "disqualifié"? Va-t-il ignorer cette chaîne comme si elle avait ignoré une valeur NULL d'un int?
+2

C'est une bonne chose que vous fassiez un cours de base de données, mais vous devriez le faire pour vous-même, sinon vous n'apprendriez pas. –

+0

Eh bien, j'apprends beaucoup, et ce cours fait partie de mon programme. J'ai juste besoin d'un peu plus d'informations pour ce rapport. – lindastralberg

Répondre

0

Vos questions peuvent être résolues par runing tests simples:

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; 

Résultat:

avg(int_col) | avg(char_col) 
    15,0000 |   15 

http://rextester.com/NNAZ9432

Comme vous pouvez le voir AVG sur une colonne VARCHAR retourne la résultat attendu.

Maintenant, ajoutez une ligne avec NULL et '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; 

Maintenant, les résultats sont différents:

avg(int_col) | avg(char_col) 
    15,0000 |   10 

http://rextester.com/RXOQAZ69820

Le reoson est: Alors que NULL est ignorée par AVG, 'disqualified' est converti en 0 et le résultat est (10 + 20 + 0)/3 = 10. Pour tester la performance, vous pouvez créer un grand tableau avec des données factices.En MariaDB avec la séquence plugiciel cela peut se faire facilement:

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; 

AVG sur INT:

select avg(int_col) from golf; 
-- query time: 187 msec 

AVG sur VARCHAR:

select avg(char_col) from golf; 
-- query time: 203 msec 

Last but not least: Vous ne devriez pas utiliser types de chaîne pour les valeurs numériques. Une raison de plus est le tri. Si vous essayez de trier les nombres stockés en tant que chaînes, vous obtiendrez quelque chose comme [10, 2, 22, 3].

Vous ne devez également pas utiliser une colonne pour différents types d'informations. Dans votre cas, vous pouvez définir une autre colonne comme status avec les valeurs 'fini' ou 'disqualifié'. Une autre façon possible est d'avoir une colonne de drapeau disqualified avec les valeurs 0 ou 1.

+0

Merci beaucoup! – lindastralberg