IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Doctrine2 PHP Discussion :

Doctrine GROUP BY ANY_VALUE [3.x]


Sujet :

Doctrine2 PHP

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2003
    Messages : 307
    Points : 378
    Points
    378
    Par défaut Doctrine GROUP BY ANY_VALUE
    Hello

    Suite aux changements de mysql 5.7.5
    https://dev.mysql.com/doc/refman/5.7...-handling.html

    Je dois refaire mon group by

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT ANY_VALUE(d.id), d.nom, count(d.nom) as lignes FROM defunts d GROUP BY d.nom ORDER BY d.nom ASC
    J'ai résolu le soucis avec un any_value, mais j'arrive pas à faire la requête avec doctrine

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $qb = $this->createQueryBuilder('d');
    $qb->select('ANY_VALUE(d.id), d.nom, count(d.nom) as lignes');
    $qb->groupBy('d.nom');   
    $qb->orderBy('d.nom');
    J'ai le message d'erreur QueryException: [Syntax Error] line 0, col 7: Error: Expected known function, got 'ANY_VALUE'

    Comment écrire ça correctement ?

    Merci

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2012
    Messages
    631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2012
    Messages : 631
    Points : 1 220
    Points
    1 220
    Par défaut
    bonjour,
    en SQL standard (différent de MYSQL ), pour compter les lignes issues de la table defunts:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT d.id, d.nom, count(d.nom) as lignes FROM defunts d GROUP BY d.id, d.nom ORDER BY d.nom ASC
    ce qui se traduit en doctrine par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $qb = $this->createQueryBuilder('d');
    $qb->select('d.id, d.nom, count(d.nom) as lignes');
    $qb->groupBy('d.id'); 
    $qb->addGroupBy('d.nom') ; 
    $qb->orderBy('d.nom')
    Citation Envoyé par jfsenechal Voir le message
    Hello

    Suite aux changements de mysql 5.7.5
    https://dev.mysql.com/doc/refman/5.7...-handling.html

    Je dois refaire mon group by

    Merci
    en sql standard on ne peut pas effectuer un groupement d'un champ qui ne se trouve pas dans le SELECT ce que MySQL<5.7 laissait passer.ANY-VALUE() n'a pour but que d'exclure du GROUP BY un champ sélectionné .Par exemple, la requête suivante fonctionne pour MySQL<5.7 mais elle est incorrecte pour SQL standard ou pour MySQL 5.7:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT d.id, d.nom, count(d.nom) as lignes FROM defunts d GROUP BY d.nom ORDER BY d.nom ASC
    La requête suivante suivante fonctionne que pour MySQL 5.7
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT ANY_VALUE(d.id), d.nom, count(d.nom) as lignes FROM defunts d GROUP BY d.nom ORDER BY d.nom ASC
    en revanche, la requête suivante compatible SQL standard fonctionnera quel que soit le moteur de BD( MySQL*, SQL Server, Oralce ...):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT d.id, d.nom, COUNT(d.nom) as lignes FROM defunts d GROUP BY d.id, d.nom ORDER BY d.nom ASC
    J'ai le message d'erreur QueryException: [Syntax Error] line 0, col 7: Error: Expected known function, got 'ANY_VALUE'
    ANY_VALUE n'est pas supportée par doctrine2

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2003
    Messages : 307
    Points : 378
    Points
    378
    Par défaut
    Merci armel18 pour toutes ces explications

    Mais j'avais déjà essayé en groupant aussi l'id mais le résultat obtenu n'est pas ce que je veux

    Je veux sélectionner tous les noms différents dans la table défunt avec le nbre de fois que ceux ci apparaissent,comme ici http://sepulture.marche.be/patronyme/

    En groupant avec l'id j'obtient ce genre de résultat

    Nom : Capture du 2017-01-01 15-36-42.png
Affichages : 2920
Taille : 103,4 Ko

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2012
    Messages
    631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2012
    Messages : 631
    Points : 1 220
    Points
    1 220
    Par défaut
    si j'arrive bien à comprendre ton modèle, le champ ligne ne devrait pas figurer dans la table defunts car il oblige à dupliquer le champ nom.Le champ ligne devrait être une table de jointure entre defunts et parcelle: defunts_parcelle(defunts_id, parcelle_id) ce qui implique la relation @ManyToMany dans l'entité defunts et/ou dans l'entité parcelle.De ce modèle, pour compter le nombre de parcelles par personne il suffit de compter le nombre de fois où defunts_id apparaît dans la table defunts_parcelle.

    Après si ne souhaites pas apporter des modifs sur ton modèle, plusieurs choix sont possibles:
    -désactiver le strict_mode de MySQL5.7 pour permettre aux anciennes requêtes fonctionnant sur MySQL<5.7 de continuer à fonctionner sur la version récente de MySQL.Dans le fichier de config de MySQL, tu ajoutes ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #/etc/mysql/my.cnf
    [mysqld] 
    #Désactive le strict mode
    sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    -Écrire une extension doctrine pour la fonction ANY_VALUE pour pouvoir l'utiliser dans une requête doctrine.

  5. #5
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2003
    Messages : 307
    Points : 378
    Points
    378
    Par défaut
    la relation est many to one pour le defunt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    /**
         * @ORM\ManyToOne(targetEntity="Sepulture", inversedBy="defunts")
         * @ORM\JoinColumn(name="sepulture_id", referencedColumnName="id")
         * */
        private $sepulture;
    et une one to many pour la sépulture

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     /**
         * @ORM\OneToMany(targetEntity="Defunt", mappedBy="sepulture", cascade={"remove"})
         * @ORM\OrderBy({"nom" = "ASC"})
         * */
        private $defunts;
    je pense que c'est correcte ?

    Ma colonne ligne, que j'aurais pu appeler autrement indique le nbre de fois que le nom de famille "adam" apparait

    Je vais pas créer une fonction doctrine pour une requête des plus basique

    Oui je pourrais changer la config de mysql mais c'est pas normal d'en arriver là pour une si simple requête :-(

  6. #6
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2012
    Messages
    631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2012
    Messages : 631
    Points : 1 220
    Points
    1 220
    Par défaut
    Citation Envoyé par jfsenechal Voir le message
    la relation est many to one pour le defunt

    je pense que c'est correcte ?

    Ma colonne ligne, que j'aurais pu appeler autrement indique le nbre de fois que le nom de famille "adam" apparait

    Je vais pas créer une fonction doctrine pour une requête des plus basique

    Oui je pourrais changer la config de mysql mais c'est pas normal d'en arriver là pour une si simple requête :-(
    l'extension doctrine de ANY_VALUE() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    <?PHP
    //src/MyBundle/DoctrineExtensions/Utils/AnyValue.php
     
    namespace DoctrineExtensions\Utils;
     
    use Doctrine\ORM\Query\AST\Functions\FunctionNode;
    use Doctrine\ORM\Query\Lexer;
    use Doctrine\ORM\Query\Parser;
    use Doctrine\ORM\Query\SqlWalker;
     
    class AnyValue extends FunctionNode {
     
    	public $value; // la valeur  passée en paramètre de la fction ANY_VALUE()
     
    	public function parse( Parser $parser ) {
    		$parser->match( Lexer::T_IDENTIFIER ); //identifie la fonction ANY_VALUE() de mysql
    		$parser->match( Lexer::T_OPEN_PARENTHESIS ); //parenthèse ouvrante
    		$this->value = $parser->StringPrimary();
    		$parser->match( Lexer::T_CLOSE_PARENTHESIS );////parenthèse fermante
    	}
     
    	public function getSql( SqlWalker $sqlWalker ) {
    		return 'ANY_VALUE(' . $this->value->dispatch( $sqlWalker ) . ')';
    	}
    }
    déclaration de la classe d'extension doctrine ( avec une clé nommée ANY_VALUE) dans le fichier config.yml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    #app/config/config.yml
    doctrine:
        dbal:
            driver:   pdo_mysql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  utf8mb4
            default_table_options:
                        charset: utf8mb4
                        collate: utf8mb4_unicode_ci
     
        orm:
            auto_generate_proxy_classes: %kernel.debug%
            default_entity_manager: default
            entity_managers:
                default:
                    auto_mapping: true
                    connection: default
                    dql:
                        string_functions:
                            ANY_VALUE: DoctrineExtensions\Utils\AnyValue
    la requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //ANY_VALUE représente la clé contenue dans le fichier config.yml
    $qb = $this->createQueryBuilder('d');
    $qb->select('ANY_VALUE(d.id), d.nom, count(d.nom) as lignes');
    $qb->groupBy('d.nom');   
    $qb->orderBy('d.nom')
    Il existe une lib des extensions doctrine beberlei/DoctrineExtensions mais elle ne supporte pas encore certaines nouveautés(peut être toutes les nouveautés) de MySQL5.7 dont ANY_VALUE(), c'est pour cela qu'il écrire soi même son extension .

    Entre temps doctrine te laisse aussi la possibilité d'écrire ta requête en SQL native.

  7. #7
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Février 2003
    Messages : 307
    Points : 378
    Points
    378
    Par défaut
    je ne connaissais pas ces extensions,
    super pour ta réponse complète armel18

    :-)

    je passe en résolu ;-)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Doctrine] Le GROUP BY à revisiter
    Par MightyDucks dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 29/09/2011, 11h54
  2. Doctrine et group by
    Par rastaferraille dans le forum ORM
    Réponses: 3
    Dernier message: 20/08/2010, 22h30
  3. [RaveReport] - Bloquer groupe sur une page
    Par muaddib dans le forum Rave
    Réponses: 3
    Dernier message: 25/02/2003, 16h21
  4. gestion des groupes
    Par muaddib dans le forum QuickReport
    Réponses: 3
    Dernier message: 31/12/2002, 11h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo