Partage
  • Partager sur Facebook
  • Partager sur Twitter

fonction MIN en SQL

    25 août 2010 à 22:30:27

    Bonjour tout le monde!

    Je suis un habitué de Visual Basic et mes réflexes en SQL en sont donc affectés lol

    Supposons que x est ma variable, j'essaie de faire une condition tel que:

    where 
    ...
    ...
    and x in (min(x),min(x)+1)
    


    Cela me retourne l'erreur : group function is not allowed here.

    Je pourrais faire un Query dans une Query, mais je ne suis pas assez familier.
    J'ai essayé avec HAVING, mais sans succès

    Il doit nécessairement avoir une méthode facile pour y arriver?
    MERCI A TOUS!!
    • Partager sur Facebook
    • Partager sur Twitter
      25 août 2010 à 22:57:40

      select * from table where x BETWEEN min(x) AND min(x)+1
      


      ça n'as pas lair de marcher non plus...

      peut etre fais en deux fois

      select min(x) from table
      


      et ensuite tu recupere la valeur pour linsérer dans ta requete
      • Partager sur Facebook
      • Partager sur Twitter
        25 août 2010 à 23:05:26

        Le BETWEEN ne fonctionne pas non plus malheureusement.
        Même message d'erreur.
        C'était une bonne idée par contre, merci!

        SQL ne peut apparemment pas traiter ce genre de "loop"(contrairement à Visual Basic qui lui prendrait ma condition sans problème)

        Je viens d'essayer de faire une query dans ma query.
        En fait c'est même DEUX query dans ma query, puisque je dois le faire pour min(x) et pour min(x)+1.
        Et comme j'ai vraiment beaucoup de conditions dans ma query original, je dois tous les répéter. AIE, c'est pas super esthétique.
        Mais bonne nouvelle....ça roule! Bon, ça ne donne pas ce que je veux, mais j'approche.

        • Partager sur Facebook
        • Partager sur Twitter
          25 août 2010 à 23:09:23

          Attention je suis pas un pro de mysql mais les query dans les query j'ai tenté c'est la mort en performance... je crois qu'avec une certaine jointure et des alias peut etre left outer join tu doit pouvoir faire ça, mais je me souviens plus trop je vais chercher un peu
          • Partager sur Facebook
          • Partager sur Twitter
            25 août 2010 à 23:12:58

            Tu ne peux pas utiliser de fonction d'agrégation dans un WHERE, il faut utiliser la clause GROUP BY, auquel cas il faudra utiliser également HAVING.
            • Partager sur Facebook
            • Partager sur Twitter
              25 août 2010 à 23:17:58

              SELECT * from table HAVING x BETWEEN min(x) AND min(x)+1
              


              c'était simple en fait....^^
              • Partager sur Facebook
              • Partager sur Twitter
                26 août 2010 à 0:39:21

                Sauf que la clause HAVING ne sert pas à ça, mais à filtrer les groupes (donc, avec une requête incluant GROUP BY)...

                La première solution qui me vient en tête aurait été deux sous-requêtes :

                -- ...
                WHERE x BETWEEN (SELECT MIN(x) FROM table_name) AND (SELECT MIN(x) + 1 FROM table_name)
                


                Après, c'est peut-être pas la solution la plus efficace, quoi qu'il en soit, ça reste plus approprié que le HAVING (qui ne fonctionnerait même pas avec un SGBDR potable)
                • Partager sur Facebook
                • Partager sur Twitter
                  26 août 2010 à 11:44:20

                  mm tu as surement raison mais en tout cas le HAVING est carrement plus rapide ici que ta requete ci dessus
                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 août 2010 à 11:58:39

                    Sauf qu'il n'y a que MySQL qui accepte HAVING sans la clause GROUP BY (tiens, comme par hasard), que c'est très moche et que ça ne renvoie pas toujours le résultat voulu.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      26 août 2010 à 17:00:16

                      Citation : BlueRat

                      Sauf qu'il n'y a que MySQL qui accepte HAVING sans la clause GROUP BY (tiens, comme par hasard), que c'est très moche et que ça ne renvoie pas toujours le résultat voulu.


                      Petite question, ça fait quoi un HAVING sans GROUP BY ? Elle porte sur quoi la condition du HAVING ?
                      • Partager sur Facebook
                      • Partager sur Twitter

                      "'But I don't want to go among mad people,' said Alice. 'Oh, you can't help that,' said the cat. 'We're all mad here.'" Lewis Carroll

                        26 août 2010 à 17:17:06

                        Le HAVING est au GROUP BY ce que le WHERE est au SELECT.
                        Imagine que tu comptes la somme des salaires de chaque employé d'une entreprise, ces derniers étant regroupé par département (financier, marketing, informatique, etc.)
                        Supposons que tu ne veuilles que les département où la somme des salaires soit supérieure à 30000, c'est à ce moment là qu'il faudra utiliser le HAVING SUM(salaire) >= 30000.

                        D'ailleurs un HAVING sans GROUP BY sous Oracle affiche un très joli message d'erreur ^^
                        • Partager sur Facebook
                        • Partager sur Twitter
                          26 août 2010 à 17:26:01

                          Citation : BlueRat


                          Supposons que tu ne veuilles que les département où la somme des salaires soit supérieure à 30000, c'est à ce moment là qu'il faudra utiliser le HAVING SUM(salaire) >= 30000.


                          Et dans ce cas là, on regroupe par département dans le GROUP BY, je suis bien d'accord ;)

                          (en passant, on ne peut pas utiliser des GROUP BY et de HAVING pour le problème posé par lilpac, étant donné que sa condition porte bien sur les lignes et pas sur des regroupements de lignes)

                          Mais si je reprends un select avec un HAVING sans GROUP BY, comme celui qui est plus haut :
                          SELECT * from table HAVING x BETWEEN min(x) AND min(x)+1
                          

                          C'est quoi la sémantique de ce truc ? Toutes les lignes sont placées dans un même groupe et si la condition est fausse, la requête retourne 0 lignes ?

                          Citation : BlueRat


                          D'ailleurs un HAVING sans GROUP BY sous Oracle affiche un très joli message d'erreur ^^


                          +1 pour Oracle :p
                          • Partager sur Facebook
                          • Partager sur Twitter

                          "'But I don't want to go among mad people,' said Alice. 'Oh, you can't help that,' said the cat. 'We're all mad here.'" Lewis Carroll

                            26 août 2010 à 21:58:53

                            Citation : Fayden


                            La première solution qui me vient en tête aurait été deux sous-requêtes :

                            -- ...
                            WHERE x BETWEEN (SELECT MIN(x) FROM table_name) AND (SELECT MIN(x) + 1 FROM table_name)
                            





                            C'est exactement le chemin que je me suis résolu à emprunter. (une query dans une query youpi!)

                            Concernant cette façon de faire, dois-je répéter toutes mes conditions de la query principale?

                            SELECT a, b
                            FROM table1, table2, table3
                            WHERE c = d
                            and e = f
                            -- ...
                            and x BETWEEN (SELECT MIN(x) FROM table3 WHERE "?!?!?") AND (SELECT MIN(x) + 1 FROM table_name WHERE "?!?!?!")
                            


                            Donc, dans les "?!?!?!" dois-je y mettre mes conditions principales c = d et e = f

                            Pas nécessaire? Permet d'optimiser? Ralentir?

                            Pas évident d'être clair à l'écrit :p
                            Merci encore pour votre aide à tous!
                            • Partager sur Facebook
                            • Partager sur Twitter
                              26 août 2010 à 22:10:50

                              Bah, ça dépend de ce que tu veux sélectionner. La sous-requête va nécessairement sélectionner le plus petit x s'il n'y a pas de WHERE. Bref, c'est toi qui vois.

                              Je sais pas si ça serait plus efficace de faire deux requêtes séparées : l'une qui va chercher la valeur MIN(x) puis l'autre qui fait ce que tu veux. Le problème avec les deux sous-requêtes (solution que j'ai proposée), c'est qu'on va chercher deux fois la même information, ce qui devrait logiquement être évité si on pouvait stocker le résultat dans une variable.

                              Je doute toutefois que de faire deux requêtes distinctes soit plus lent à cause du langage qui traite le résultat des requêtes.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                26 août 2010 à 22:26:29

                                Mouais, ça dépend de ce que l'on veut je comprend.

                                Je pourrais tenter d'expliquer, mais on va plutôt tous se mélanger loll
                                Ha puis enfin, je m'essaie. C'est complémentaire, vous m'avez déjà mis sur la bonne piste ;) merci! Pour les curieux, vous pouvez continuer à lire :p

                                ---------------------------

                                En gros, j'ai 6 tables.
                                Dans chaque, il y a le même nombre de lignes qui ont chacun un numéro unique, disons de 1 à 100.
                                Dans chaque table, il y a différentes colonnes.
                                Donc bref, TOUT pourrait être grosso modo dans la même table, mais cette table aurait énormément de colonnes.

                                Je fais des conditions sur certaines colonnes de chaque tables, afin d'obtenir en bout de ligne y numéros uniques parmi les 100.

                                Puis, dernière étape je prend ces y valeurs et je demande de me sortir les informations x BETWEEN min(x) AND min(x)+1) associées à y.

                                Donc bref,le min(x) a seulement besoin de rouler sur les x qui m'intéressent et non pas tous.
                                C'est pour cette raison que je crois que je dois répéter mes conditions ou plutôt, je ne suis pas obligé, mais ça permet d'optimiser je crois.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  27 août 2010 à 0:37:26

                                  C'est effectivement difficile de comprendre, il faudrait savoir à quoi les tables correspondent concrètement.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    27 août 2010 à 18:10:24

                                    Citation : lilpac

                                    Donc bref,le min(x) a seulement besoin de rouler sur les x qui m'intéressent et non pas tous.


                                    MIN est une fonction agissant sur un ensemble de lignes. Si elle ne doit considérer que certaines lignes de ta table, alors oui, il faut re-spécifier une condition dans les WHERE du sous-SELECT ;)

                                    Si MySQL est bien conçu, pour deux sous-SELECTs ayant une même déclaration, il ne devrait exécuter la sous-requête qu'une seule fois ^^ (mais là il faut aller voir dans la doc comment afficher le plan d'exécution de ta requête).
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    "'But I don't want to go among mad people,' said Alice. 'Oh, you can't help that,' said the cat. 'We're all mad here.'" Lewis Carroll

                                      27 août 2010 à 22:33:33

                                      Mais ce n'est pas la même sous requête, sachant que l'une sélectionne MIN(x), l'autre, MIN(x) + 1.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        28 août 2010 à 8:47:16

                                        Sauf si on fait (SELECT MIN(*) ...) + 1 pour la deuxième partie. Mais ce n'est pas recommandé par le manuel MySQL :-° . Il faut donc voir ce qui est le plus rapide.
                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        "'But I don't want to go among mad people,' said Alice. 'Oh, you can't help that,' said the cat. 'We're all mad here.'" Lewis Carroll

                                          28 août 2010 à 11:21:56

                                          Je vais peut-être dire une bêtise, mais on pourrait très bien faire une procédure stockée, ainsi on ne fera la requête (pour le MIN et MIN+1) qu'une seule fois.
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          fonction MIN en SQL

                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                          • Editeur
                                          • Markdown