[RAILS] Une erreur s'est produite car le only_full_group_by de sql_mode n'a pas été observé.

problème

スクリーンショット 2020-11-04 午後1.44.09.png

Lorsque j'ai essayé d'afficher le graphique, l'erreur suivante s'est affichée.

Mysql2::Error: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'pfc-master_production.posts.created_at' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by: SELECT `posts`.`created_at` FROM `posts` WHERE `posts`.`user_id` = 8 GROUP BY date(created_at)

charts_controller.rb


@dates = dates_calorie.map { |dates| dates.created_at }

Lire le journal des erreurs

Mysql2::Error: Expression #1 of SELECT list is not in GROUP BY clause and 
Mysql2 ::Erreur: l'expression n ° 1 de la liste SELECT n'est pas dans la clause GROUP BY

contains nonaggregated column 'pfc-master_production.posts.created_at' 
which is not functionally dependent on columns in GROUP BY clause;
Colonnes non agrégées qui ne dépendent pas fonctionnellement des colonnes de la clause GROUP BY
'pfc-master_production.posts.created_at'contenait

this is incompatible with sql_mode=only_full_group_by: 
C'est sql_mode = only_full_group_Non compatible avec par

SELECT SUM(`posts`.`calorie`) AS sum_calorie, date(created_at) AS date_created_at FROM `posts` WHERE `posts`.`user_id` = 8 GROUP BY date(created_at) ORDER BY created_at DESC

** Quelle est la méthode de la carte? ** **

・ En un mot, la méthode map est "une méthode qui exécute le traitement de chaque élément dans l'ordre". -Accédez à chaque élément et effectuez le traitement demandé. [Introduction to Rails] Capturez complètement la méthode de la carte! Apprenez les bases de la manipulation de tableaux

Variable de tableau.map {|Nom de variable|Traitement spécifique}

Dans ce cas
@dates = dates_calorie.map(Variable de tableau) { |dates(Nom de variable)| dates.created_at(En traitement) }

** Que contient le tableau dates_calorie? ** **

dates_calorie = current_user.posts.group("date(created_at)").select(:created_at)

S'il y a plusieurs messages par l'utilisateur connecté dans une journée, ceux qui sont regroupés par jour et obtiennent la colonne created_at sont inclus. Autrement dit, une colonne created_at est acquise par jour et les informations de la colonne created_at pour chaque jour sont contenues dans le tableau.

La raison d'obtenir ces informations est d'implémenter un graphique qui montre le poids quotidien. En effet, lorsqu'il y a plusieurs publications par jour, je souhaite n'en afficher qu'une par jour sur le graphique.

✖️ [2020-11-09 00:00:00, 2020-11-09 00:11:00, 2020-11-10 00:12:00] ○ [2020-11-09 00:00:00, 2020-11-10 00:12:00, 2020-11-11 00:12:00]

** Quel type de traitement effectuez-vous en utilisant la méthode cartographique? ** **

@dates = dates_calorie.map(Variable de tableau) { |dates(Nom de variable)| dates.created_at(En traitement) }

Comme expliqué ci-dessus, le tableau dates_calorie contient tous les jours created_ats dans le tableau, que vous pouvez utiliser la méthode map pour placer chaque élément du tableau dans une variable appelée dates. Sortez-le et soyez créé_at.

Ils sont affectés à des variables d'instance à utiliser dans les graphiques en les transmettant à chart.js, qui affiche les graphiques avec gon.

Pourquoi avez-vous eu une erreur cette fois?

Je ne connaissais pas only_full_group_by, alors j'ai recherché only_full_group_by dans la référence.

** Qu'est-ce que sql_mode = only_full_group_by? ** **

Rejette les requêtes référencées par des listes de sélection, des conditions HAVING ou (depuis MySQL 5.6.5) des listes ORDER pour les colonnes non agrégées qui ne sont pas nommées dans la clause GROUP BY.

Si> ONLY_FULL_GROUP_BY est actif, la requête suivante n'est pas valide. La première est que la colonne d'adresse non agrégée dans la liste de sélection n'est pas nommée dans la clause GROUP BY et la seconde n'est pas valide car max_age dans la clause HAVING n'est pas nommée dans la clause GROUP BY. Devenir.

Qu'est-ce que la référence MySQL ONLY_FULL_GROUP_BY?

sql_mode est comme les règles officielles de MySQL, et only_full_group_by semble être une règle nouvellement définie dans MySQL 5.6.5 ou version ultérieure.

-Il est probable qu'une erreur se soit produite car la règle de only_full_group_by n'a pas été suivie. -Il est probable qu'une erreur s'est produite car le nom n'a pas été spécifié dans la clause GROUP BY.

** Qu'est-ce que la clause GROUP BY? ** **

select [Nom de l'élément à afficher] from [nom de la table] GROUP BY [Nom de l'élément à regrouper];
SELECT team, COUNT(team) FROM user GROUP BY team;

Contre-mesures

De ce qui précède, il existe deux contre-mesures possibles.

(1) Modifiez le code pour utiliser la clause GROUP BY afin de respecter le mode SQL only_full_group_by. (2) Modifiez my.cnf (fichier de paramètres MySQL) et supprimez la restriction de only_full_group_by.

Cette fois, j'ai choisi la méthode (2). La raison est que je n'ai pas le temps.

Maintenant que je commence à changer de poste en ingénieur Web, je dois pouvoir montrer l'application au responsable du recrutement de l'entreprise dès que possible. En fait, ① est souhaitable, mais cette fois j'ai choisi ② parce que le temps est prioritaire.

Cette solution

my.Trouvez l'emplacement de conf
[naota@ip-10-0-0-32 ~]$ mysql --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 

my.Ouvrir la conf
[naota@ip-10-0-0-32 ~]$ vi /etc/my.cnf

Utilisé lors de l'écrasement d'un fichier en lecture seule
:w !sudo tee %

La description suivante a été ajoutée à «my.conf».

my.conf


[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

J'ai vérifié sql_modes tels que NO_ZERO_IN_DATE et NO_ZERO_DATE, mais j'ai trouvé qu'il n'y avait aucun intérêt à désactiver ʻonly_full_group_by en eux-mêmes. Probablement, il n'est pas défini sur ʻonly_full_group_by dans le paramètre ci-dessus, mais il n'est pas défini car il n'est pas écrit en incluant ʻonly_full_group_by`.

→ ʻOnly_full_group_by` Cette hypothèse était correcte car l'erreur au début s'est produite lorsque je l'ai ajoutée.

J'ai redémarré MySQL pour que les paramètres ci-dessus prennent effet.

J'ai eu une erreur avec only_full_group_by après la mise à jour vers MySQL 5.7

Arrêtez MySQL
[naota@ip-10-0-0-32 ~]$ sudo systemctl stop mysqld.service

Démarrez MySQL
[naota@ip-10-0-0-32 ~]$ sudo systemctl start mysqld.service

Le graphique est affiché! スクリーンショット 2020-11-04 午後1.45.51.png

Code source

charts_controller.rb est un contrôleur pour afficher des graphiques.

charts_controller.rb


def index
    #calorie
    @sampleuser = User.find_by(id: 3)
    if user_signed_in?
      #Calculer le total des calories par date
      sum_calorie = current_user.posts.group("date(created_at)").sum(:calorie)
      #Étant donné que le total des calories pour chaque date est sous la forme d'un hachage, obtenez la valeur, mettez-la dans un tableau et affectez-la à une variable
      array_calorie = sum_calorie.values
    else
      sum_calorie = @sampleuser.posts.group("date(created_at)").sum(:calorie)
      array_calorie = sum_calorie.values
    end
    #Passer des données au côté js en utilisant gon
    gon.data = []
    #Extraire les calories totales pour chaque date une par une avec la méthode de la carte
    #Comment utiliser la méthode de la carte → Variable Array.map {|Nom de variable|Traitement spécifique}
    gon.data = array_calorie.map { |calorie| calorie }

    if user_signed_in?
      #Créé par date_Obtenez uniquement à la colonne. Stocké sous la forme d'un tableau
      dates_calorie = current_user.posts.group("date(created_at)").select(:created_at)
    else
      dates_calorie = @sampleuser.posts.group("date(created_at)").select(:created_at)
    end

    gon.date = []
    @dates = dates_calorie.map { |dates| dates.created_at }
    #Retirez et modifiez la notation de la date une par une dans chaque instruction
    @dates.each do |a|
      gon.date << a.strftime("%Y année%m mois%jour j")
    end


    #poids
    if user_signed_in?
      gon.weight = current_user.posts.group("date(created_at)").select(:weight).map { |weight| weight[:weight] }
    else
      gon.weight = @sampleuser.posts.group("date(created_at)").select(:weight).map { |weight| weight[:weight] }
    end
  end

Recommended Posts

Une erreur s'est produite car le only_full_group_by de sql_mode n'a pas été observé.
[Rejeté] Un mémorandum car une erreur s'est produite lors du déploiement dans Heroku
Un exemple d'erreur FactoryBot [KeyError: Factory not registered: "user"]
[Opération non autorisée] Un mémorandum car une erreur s'est produite lors de la création d'une instance EC2.
Lors de l'introduction de JOOQ dans Spring Boot, une histoire qui a été traitée parce qu'une erreur s'est produite autour de Liquidbase