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

Langage SQL Discussion :

Comment trier sur des adresses IP au format NVARCHAR


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mai 2014
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2014
    Messages : 26
    Points : 23
    Points
    23
    Par défaut Comment trier sur des adresses IP au format NVARCHAR
    Bonjour à tous,

    Je m'arrache mes derniers cheveux à chercher une solution pour trier le contenu d'une table sur une colonne NVARCHAR contenant plusieurs centaines d'adresses IP de divers formats
    10.12.1.106
    192.101.204.1
    1.123.12.17
    etc... et pour l'instant aucune solution ne fonctionne.

    Est-ce que quelqu'un aurait une solution à me proposer?

    Par avance merci et cordiales salutations à tous
    André

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 311
    Points : 39 673
    Points
    39 673
    Billets dans le blog
    9
    Par défaut
    Quel est le problème ? Quel est le résultat attendu et le résultat obtenu ?.
    Si vous voulez influencer le tri des chaines de caractères, il faut jouer avec la collation : ORDER BY ma_colonne COLLATE ma_collation .

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Ingénieur d'Etude Mainframe/AS400
    Inscrit en
    Novembre 2012
    Messages
    1 767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur d'Etude Mainframe/AS400
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2012
    Messages : 1 767
    Points : 10 775
    Points
    10 775
    Par défaut
    Bonjour, la question est fonctionnelle plus que technique. Quel est le critère de tri sur ces adresses IP ? Est-ce triplet par triplet ?

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Déjà, il y a un problème de modélisation.
    En effet, une IP est une série de 4 bytes.

    Par conséquent, au lieu de stocker ça dans un nvarchar(15) (soit plus de 30 bytes) il aurait été préférable de stocker ça dans un binary(4)

    Ceci aurait permis :
    - de diviser par 8 l'espace requis pour le stockage de vos IP !
    - de corriger d'emblée votre problème de tri
    - de permettre de valider que chaque partie de l'IP est bien comprise entre 0 et 255 sans coder quoi que ce soit
    - pouvoir effectuer aisément des recherches avec des masques réseaux (qui ne sont au final que des masques binaires)

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 881
    Points : 53 060
    Points
    53 060
    Billets dans le blog
    6
    Par défaut
    Non, en fait une adresse IP V4 c'est juste un entier de 32 bits…
    Il suffit de le coder sous forme d'entier 32 bits et le tri est simple !
    C'est la représentation qui en est fait sous forme de 4 petits entiers plus simple à mémoriser/utiliser, tout comme on présente les n° de téléphone par groupe de 2 (France) ou 3 chiffres (US).

    Pour information, j'ai posté il y a fort longtemps ce puzzle :
    https://sqlpro.developpez.com/Exerci...e=part-3#LIV-H

    Qui est très proche de votre problématique….
    La solution est la suivante (sous SQL Server) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    --> soit la table 
    CREATE TABLE TIP
    (TIP_ID     INT PRIMARY KEY,
     TIP_ADR    VARCHAR(15));
    GO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    --> contenant les adresses IP suivantes :
    INSERT INTO TIP VALUES (1, '10.120.12.1');
    INSERT INTO TIP VALUES (2, '10.130.201.159');
    INSERT INTO TIP VALUES (3, '10.130.23.1');
    INSERT INTO TIP VALUES (4, '10.130.201.1');
    INSERT INTO TIP VALUES (5, '10.13.11.1'); 
    INSERT INTO TIP VALUES (6, '10.130.201.5');
    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
    --> la requête suivante :
    WITH 
    T AS 
    (
    SELECT TIP_ID, TIP_ADR AS ORIGINAL_IP, 
           SUBSTRING(TIP_ADR, 1, CHARINDEX('.', TIP_ADR) - 1) AS BIP_ADR1,
           SUBSTRING(TIP_ADR, CHARINDEX('.', TIP_ADR) + 1, LEN(TIP_ADR) - CHARINDEX('.', TIP_ADR)) AS TIP_ADR
    FROM   TIP
    ),
    TT AS
    (SELECT TIP_ID, ORIGINAL_IP, BIP_ADR1, SUBSTRING(TIP_ADR, 1, CHARINDEX('.', TIP_ADR) - 1) AS BIP_ADR2,
            SUBSTRING(TIP_ADR, CHARINDEX('.', TIP_ADR) + 1, LEN(TIP_ADR) - CHARINDEX('.', TIP_ADR)) AS TIP_ADR
    FROM T)
    SELECT TIP_ID, ORIGINAL_IP,
           CAST(BIP_ADR1 AS TINYINT) AS BIP_ADR1,
           CAST(BIP_ADR2 AS TINYINT) AS BIP_ADR2,
           CAST(SUBSTRING(TIP_ADR, 1, CHARINDEX('.', TIP_ADR) - 1) AS TINYINT) AS BIP_ADR3,
           CAST(SUBSTRING(TIP_ADR, CHARINDEX('.', TIP_ADR) + 1, LEN(TIP_ADR) - CHARINDEX('.', TIP_ADR)) AS TINYINT) AS BIP_ADR4
    FROM    TT
    ORDER BY 3, 4, 5, 6
    Permet un tel tri. Elle est cependant horriblement couteuse du fait du modèle de données pourri !

    Il existe une autre solution via une requête récursive…. Elle est encore moins performante !

    A +

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 881
    Points : 53 060
    Points
    53 060
    Billets dans le blog
    6
    Par défaut
    Et voici la version récursive…

    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
    WITH
    T AS(SELECT TIP_ADR AS TIP_IP, TIP_ID, 2 AS POS,
                CAST(LEFT(TIP_ADR, CHARINDEX('.', TIP_ADR) - 1) AS FLOAT) * POWER(2, 24) AS ADR_IP_NUM,
                RIGHT(TIP_ADR, LEN(TIP_ADR) - CHARINDEX('.', TIP_ADR)) + '.' AS TIP_ADR
         FROM   TIP
         UNION ALL
         SELECT TIP_IP, TIP_ID, POS -1,
                ADR_IP_NUM + CAST(LEFT(TIP_ADR, CHARINDEX('.', TIP_ADR) - 1) AS FLOAT) * POWER(2, 8*POS) AS ADR_IP_NUM,
                RIGHT(TIP_ADR, LEN(TIP_ADR) - CHARINDEX('.', TIP_ADR)) AS TIP_ADR
         FROM   T
         WHERE  POS >= 0
    )
    SELECT TIP_ID, TIP_IP AS TIP_ADR
    FROM   T 
    WHERE  POS = -1 
    ORDER BY ADR_IP_NUM;
    A +

Discussions similaires

  1. Trier sur une adresse IP au format numérique
    Par grenoult dans le forum Langage
    Réponses: 1
    Dernier message: 06/10/2008, 13h15
  2. Etats: trier sur des totaux
    Par Pierren dans le forum IHM
    Réponses: 4
    Dernier message: 07/02/2006, 12h28
  3. [Oracle 9.2.0.7] Comment updater sur des clés de partition ?
    Par le_nullos_des_nullos dans le forum Oracle
    Réponses: 3
    Dernier message: 05/02/2006, 00h26
  4. Select sur des nombre décimaux de format 0.*
    Par CanardJM dans le forum Langage SQL
    Réponses: 8
    Dernier message: 18/08/2005, 16h04
  5. [VB6] Comment boucler sur des controls d'un form ?
    Par lankviller dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 27/01/2003, 16h29

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