Fonctions Analytiques ROW_NUMBER et DENSE_RANK

Les fonctions analytiques sont très puissantes et très utiles, elles permettent d’alléger les requêtes SQL d’une façon élégante et performante.
Une fonction que j’ai utilisée récemment est la fonction ROW_NUMBER, elle permette de donner un ordre numérique pour les lignes, la pseudo-colonne ROWNUM existe mais son utilisation nécessite l’écriture de plus d’instruction.
Voila un exemple qui illustre l’utilité de cette fonction ; supposons que vous voulez faire un ordre sur la colonne salaire de la table EMP du schéma SCOTT :   

SQL> select EMPNO,ENAME,SAL
  2  from scotty.emp order by SAL;
     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             800
      7900 JAMES             950
      7876 ADAMS            1100
      7521 WARD             1250
      7654 MARTIN           1250
      7934 MILLER           1300
      7844 TURNER           1500
      7499 ALLEN            1600
      7782 CLARK            2450
      7698 BLAKE            2850
      7566 JONES            2975
     EMPNO ENAME             SAL
---------- ---------- ----------
      7788 SCOTT            3000
      7902 FORD             3000
      7839 KING             5000
14 ligne(s) selectionnee(s).

Ajoutons une colonne pour le classement de ces lignes selon le salaire, si on utilise directement ROWNUM ça marcherai pas :
SQL> select EMPNO,ENAME,SAL, rownum classement from scotty.emp order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950         12       7876 ADAMS            1100         11       7521 WARD             1250          3       7654 MARTIN           1250          5       7934 MILLER           1300         14       7844 TURNER           1500         10       7499 ALLEN            1600          2       7782 CLARK            2450          7       7698 BLAKE            2850          6       7566 JONES            2975          4
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000          8       7902 FORD             3000         13       7839 KING             5000          9
14 ligne(s) selectionnee(s).

Certes il a classé les donner mais c’est donne l’ordre de l’extraction des lignes mais pas dans l’ordre des valeurs des salaires, pour corriger ça  il faut écrire :
SQL> select EMPNO,ENAME,SAL,rownum classement from 
 2 (select EMPNO,ENAME,SAL from scotty.emp order by SAL) ;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          5       7934 MILLER           1300          6       7844 TURNER           1500          7       7499 ALLEN            1600          8       7782 CLARK            2450          9       7698 BLAKE            2850         10       7566 JONES            2975         11
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         12       7902 FORD             3000         13       7839 KING             5000         14
14 ligne(s) selectionnee(s).

C’est la que devienne l’utilisation des fonctions analytiques intéressante,  voila le même résultat en utilisant ROW_NUMBER :
SQL> select EMPNO,ENAME,SAL, row_number() over(order by SAL) classement
  2  from scotty.emp
  3  order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          5       7934 MILLER           1300          6       7844 TURNER           1500          7       7499 ALLEN            1600          8       7782 CLARK            2450          9       7698 BLAKE            2850         10       7566 JONES            2975         11
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         12       7902 FORD             3000         13       7839 KING             5000         14
14 ligne(s) selectionnee(s).

Le résultat est bien trier selon les valeurs des salaires et il est classé mais il y a un problème sur les salaires égaux  (par exemple SCOTT et FORD) ont le même salaire mais un classement différent, la aussi c’est les fonctions analytiques qui viennent  au secours :
SQL>  select EMPNO,ENAME,SAL, DENSE_RANK() over(order by SAL) classement
  2  from scotty.emp
  3  order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          4       7934 MILLER           1300          5       7844 TURNER           1500          6       7499 ALLEN            1600          7       7782 CLARK            2450          8       7698 BLAKE            2850          9       7566 JONES            2975         10
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         11       7902 FORD             3000         11       7839 KING             5000         12
14 ligne(s) selectionnee(s).

La fonction DENSE_RANK permet de donner le même classement pour les mêmes valeurs dans un résultat trié.
Chaque fois que vous écrivez des instructions SQL ou des blocs PL/SQL afin d’analyser les données, jeter un coup d’œil sur les fonctions analytiques vous pouvez y trouver un contournement.

WebSphere : JDWP error in VM_INIT: TransportException

J’ai reçu l’erreur suivant en essayant de redémarrer un serveur applicatif en Websphere .
L’erreur s’affiche dans SystemErr.log, dans SystemOut.log rien d’indicatif :

08:43:21.820 ERROR: [Agent.cpp:164] JDWP error in VM_INIT: TransportException [510/201] binding to port failed (error code: -212


En cherchant un peu cela vient de l’échec de Websphere d’obtenir le port renseigné dans  server.xml, en particulier celui de debug JVM  - c’est ce qui est indiqué par le code message JDWP – j’ai fait un grep sur la valeur debugArgs :

grep -i debugArgs ./config/cells/aix61devNode01Cell/nodes/aix61devNode01/servers/server1/server.xml
  < services xmi:type="debugservice:DebugService" xmi:id="DebugService_1319801562654" enable="true" jvmDebugPort="7777" jvmDebugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7777" BSFDebugPort="4444" BSFLoggingLevel="0"/ >
    < jvmEntries xmi:id="JavaVirtualMachine_1183122130078" verboseModeClass="false" verboseModeGarbageCollection="false" verboseModeJNI="false" runHProf="false" hprofArguments="" debugMode="true" debugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7777" genericJvmArguments="" >


Apparemment il cherche à allouer le port 7777 c’est le port par défaut pour le debugging JVM en Websphere , je fait un recherche sur le port voulu et effectivement il est déjà allouer par un autre serveur :
lsof -Pnl +M -i4 | grep 7777  

je modifie le fichier server.xml pour lui indiqué un autre port libre et voila que cela redémarre :

    < jvmEntries xmi:id="JavaVirtualMachine_1183122130078" verboseModeClass="false" verboseModeGarbageCollection="false" verboseModeJNI="false" runHProf="false" hprofArguments="" debugMode="true" debugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7788" genericJvmArguments="" >
      < systemProperties xmi:id="Property_1" name="com.ibm.security.jgss.debug" value="off" required="false"/ >

La modification peut aussi se faire au niveau console :

Un peu plus bas :

Souvenez-vous qu’en activant certains options sur WebSphere cela peut activer l’utilisation de certains ports qui ne sont pas forcement libres ou autorisé par le par-feu.