Choix mul­tiples en SQL sur IBM i : maî­tri­ser IN, CASE et sous-requêtes

Choix mul­tiples en SQL sur IBM i : maî­tri­ser IN, CASE et sous-requêtes

lun 4 février 2019 0 Par Ibmiiste

Com­ment réa­li­ser un choix mul­tiple en SQL DB2 sur IBM i

Dans le monde IBM i, beau­coup de déve­lop­peurs viennent du RPG et rai­sonnent natu­rel­le­ment en IF, SELECT/WHEN ou en boucles.
Pour­tant, SQL four­nit des méca­nismes simples et puis­sants pour expri­mer un choix mul­tiple, sou­vent de manière plus lisible et plus performante.

Petit rap­pel (utile pour tout le monde 😉) sur les prin­ci­pales approches en DB2 for IBM i.

1. Le choix mul­tiple le plus simple : l’opérateur IN

Lorsqu’on sou­haite tes­ter si une valeur appar­tient à un ensemble don­né, IN est la solu­tion la plus lisible.

SELECT *
  FROM fichiera
 WHERE A1 IN (1, 3, 5, 7);

Cette écri­ture rem­place avan­ta­geu­se­ment une suc­ces­sion de conditions :

WHERE A1 = 1
   OR A1 = 3
   OR A1 = 5
   OR A1 = 7

Pour­quoi pri­vi­lé­gier IN ?

  • meilleure lisi­bi­li­té
  • main­te­nance facilitée
  • opti­mi­sa­tion géné­ra­le­ment plus effi­cace côté DB2

Dès que plu­sieurs OR appa­raissent, IN devient un réflexe à adopter.

Source :
IBM Docu­men­ta­tion – IN pre­di­cate

Pour­quoi pri­vi­lé­gier IN ?

  • meilleure lisi­bi­li­té
  • main­te­nance facilitée
  • opti­mi­sa­tion géné­ra­le­ment plus effi­cace côté DB2

Dès que plu­sieurs OR appa­raissent, IN devient un réflexe à adopter.

Source :
IBM Docu­men­ta­tion – IN pre­di­cate

Pour­quoi pri­vi­lé­gier IN ?

  • meilleure lisi­bi­li­té
  • main­te­nance facilitée
  • opti­mi­sa­tion géné­ra­le­ment plus effi­cace côté DB2

Dès que plu­sieurs OR appa­raissent, IN devient un réflexe à adopter.

Source :
IBM Docu­men­ta­tion – IN pre­di­cate

https://www.ibm.com/docs/en/i/7.6.0?topic=predicates-in-predicate

2. Un choix mul­tiple dyna­mique avec une sous-requête

Très sou­vent, la liste des valeurs ne doit pas être codée en dur, mais pro­ve­nir d’une table.

SELECT *
  FROM fichiera
 WHERE A1 IN (
       SELECT B1
         FROM fichierb
     );

Dans ce cas :

  • A1 est com­pa­ré à toutes les valeurs retour­nées par la sous-requête
  • la règle métier est cen­tra­li­sée en base
  • on évite des trai­te­ments inter­mé­diaires côté RPG

Cas d’usage courant

  • tables de paramétrage
  • listes fonc­tion­nelles main­te­nues par les utilisateurs
  • règles métier évo­lu­tives sans recom­pi­la­tion applicative

3. Intro­duire de la logique métier avec CASE

SQL per­met d’intégrer une logique condi­tion­nelle direc­te­ment dans la requête grâce à l’expression CASE.
C’est l’équivalent concep­tuel d’un SELECT/WHEN en RPG.

SELECT *
  FROM fichiera
 WHERE A1 IN (
       SELECT
              CASE
                WHEN SUBSTR(B2, 19, 7) <> ''
                     THEN INT(SUBSTR(B2, 19, 7))
                ELSE 0
              END
         FROM fichierb
     );

Ici :

  • une valeur est extraite d’une zone alphanumérique
  • une règle de trans­for­ma­tion est appliquée
  • la com­pa­rai­son se fait sur une valeur calculée

👉 Idée clé :
Le CASE per­met de nor­ma­li­ser ou inter­pré­ter une don­née brute avant com­pa­rai­son, sans repas­ser par le code applicatif.

Source :
IBM Docu­men­ta­tion – CASE expres­sion

https://www.ibm.com/docs/en/i/7.6.0?topic=expressions-case-expression

4. Amé­lio­rer la lisi­bi­li­té avec une CTE (WITH)

Pour un SQL plus clair et plus main­te­nable, il est recom­man­dé d’isoler la logique métier dans une CTE (Com­mon Table Expres­sion).

WITH valeurs_b AS (
     SELECT DISTINCT
            CASE
              WHEN SUBSTR(B2, 19, 7) <> ''
                   THEN INT(SUBSTR(B2, 19, 7))
              ELSE 0
            END AS B3
       FROM fichierb
)
SELECT a.*
  FROM fichiera a
 WHERE a.A1 IN (SELECT B3 FROM valeurs_b);

Avan­tages

  • sépa­ra­tion claire entre cal­cul métier et fil­trage
  • SQL plus lisible et auto-documenté
  • plus simple à faire évoluer
  • approche moderne, bien adap­tée à IBM i

Source :
IBM Docu­men­ta­tion – WITH clause (CTE)

https://www.ibm.com/docs/en/i/7.6.0?topic=statement-common-table-expression

5. IN ou EXISTS : quelle différence ?

Dans cer­tains cas, on peut pré­fé­rer EXISTS :

SELECT a.*
  FROM fichiera a
 WHERE EXISTS (
       SELECT 1
         FROM fichierb b
        WHERE a.A1 =
              CASE
                WHEN SUBSTR(b.B2, 19, 7) <> ''
                     THEN INT(SUBSTR(b.B2, 19, 7))
                ELSE 0
              END
     );

À rete­nir

  • IN exprime une logique de liste de valeurs
  • EXISTS exprime une logique de rela­tion entre lignes
  • sur DB2 for IBM i, l’optimiseur choi­sit sou­vent un plan simi­laire, mais EXISTS évite cer­tains effets de bord (NULL, gros volumes)

Source :
IBM Docu­men­ta­tion – EXISTS pre­di­cate

https://www.ibm.com/docs/en/i/7.6.0?topic=predicates-exists-predicate

Conclu­sion

Le choix mul­tiple en SQL DB2 sur IBM i repose sur des construc­tions simples :

  • IN
  • sous-requêtes
  • CASE
  • CTE (WITH)

Bien uti­li­sées, elles permettent :

  • de sim­pli­fier le code RPG
  • de rap­pro­cher la logique métier des données
  • d’écrire un SQL plus lisible, plus moderne et plus maintenable

Un excellent levier pour aller vers un IBM i plus SQL-cen­tric, sans renier les fon­da­men­taux du RPG.