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

Développement SQL Server Discussion :

Requête qui retourne un nombre de lignes suivant un nombre dans un champ


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Profil pro
    Ingenieur developpement
    Inscrit en
    Septembre 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Ingenieur developpement

    Informations forums :
    Inscription : Septembre 2002
    Messages : 175
    Points : 106
    Points
    106
    Par défaut Requête qui retourne un nombre de lignes suivant un nombre dans un champ
    bonjour,

    Je suis en SQLServer 2019.

    J'aimerai avoir une requête qui me retourne un nombre de ligne suivant le contenu d'un champs.
    Exemple pour une table "Table"
    Colis Nb etiq
    1 3
    2 5

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select Colis, numEtiq from Table where colis = 1
    Remplacer NumEtiq par ?
    résultat
    1 1/3
    1 2/3
    1 3/3

    Merci pour les réponses

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 239
    Points : 12 869
    Points
    12 869
    Par défaut
    Bonjour,
    C'est faisable avec une requête récursive:
    Code sql : 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
     
    with datas(colis,nbetiq)
    as
    (
    select 1,3
    union
    select 2,5
    ),
    cte (colis,nbetiq)
    as
    (
    select colis,nbetiq
    from datas
    union all
    select cte.colis,cte.nbetiq - 1
    from datas
    inner join cte on cte.colis = datas.colis and cte.nbetiq > 0
    )
    select *
    from cte
    where nbetiq > 0
    order by colis

    J'imagine qu'il y a d'autres méthodes, mais c'est la première qui m'est venue à l'esprit.

    Tatayo.

  3. #3
    Membre régulier
    Profil pro
    Ingenieur developpement
    Inscrit en
    Septembre 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Ingenieur developpement

    Informations forums :
    Inscription : Septembre 2002
    Messages : 175
    Points : 106
    Points
    106
    Par défaut
    Merci Tatayo. Bonne idée de la requête récursive. Cela va répondre à mon besoin. Je vais en avoir une de même type. Je referais un ticket

    Code adapté
    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
    with datas(colis,nbetiq)
    as
    (
    select 1,3
    union
    select 2,5
    ),
     
    cte (colis, numEtiq, nbetiq)
    as
    (
    select colis, nbetiq, nbetiq
    from datas
    union all
    select cte.colis, cte.numEtiq - 1, cte.nbetiq
    from datas
        inner join cte on cte.colis = datas.colis and cte.numEtiq > 0
    )
     
    select colis, numEtiq, nbetiq, cast(numEtiq as varchar) + '/' + cast(nbetiq as varchar) as Etiquette
    from cte
    where numEtiq > 0
    order by colis, numEtiq

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 849
    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 849
    Points : 52 972
    Points
    52 972
    Billets dans le blog
    6
    Par défaut
    Mieux vaut avoir une table de nombre (et une table calendrier ) dans une base pour faire ce genre de chose.... Cela s'appelle des tables de comptes.... et ça existe depuis for longtemps... c'est un certain François Barrême les a inventé au 17e siècle !
    Cela évite les calculs et en particulier des requêtes récursives épouvantablement lentes (car inoptimisable...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE T_NUM (N INT PRIMARY KEY);
    GO
    INSERT INTO T_NUM VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
    GO
    INSERT INTO T_NUM 
    SELECT N1.N + 10*N2.N + 100*N3.N + 1000* N4.N + 10000*N5.N + 100000*N6.N
    FROM   T_NUM AS N1
           CROSS JOIN T_NUM AS N2
           CROSS JOIN T_NUM AS N3
           CROSS JOIN T_NUM AS N4
           CROSS JOIN T_NUM AS N5
           CROSS JOIN T_NUM AS N6
    WHERE  N1.N + 10*N2.N + 100*N3.N + 1000* N4.N + 10000*N5.N + 100000*N6.N > 9;
    Dès lors votre requête s'écrit avec une thêta jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT T.* 
    FROM   maTable AS T 
           JOIN T_NUM 
              ON N < nb_etq;
    Beaucoup plus simple et mille fois plus efficace !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 951
    Points : 4 376
    Points
    4 376
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    with data( colis, nbetiq) as (
    	select 1, 3 union all
    	select 2, 5
    )
    select colis, concat(colis, '/', k) AS label from data d
    cross apply (
    SELECT k from (
      SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) AS k FROM sys.all_objects) t WHERE k <= nbetiq  
    ) l
    ;

  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 849
    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 849
    Points : 52 972
    Points
    52 972
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par JeitEmgie Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    with data( colis, nbetiq) as (
    	select 1, 3 union all
    	select 2, 5
    )
    select colis, concat(colis, '/', k) AS label from data d
    cross apply (
    SELECT k from (
      SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) AS k FROM sys.all_objects) t WHERE k <= nbetiq  
    ) l
    ;
    Pareil, pas d'optimisation possible car lecture séquentielle des lignes. => pas ensembliste donc pas d'utilisation d'index ni de parallélisme !

    En sus la requête est dangereuse et susceptible de donner de fausses réponse. En effet, vous vous reposez sur une table système...
    1) le nombre de ligne de cette table peut être inférieur au nombre d'étiquette demandée => fausse réponse
    2) l'utilisation d'une vue système peut être interdite à un utilisateur aux privilèges restreint (en gros, seul les DBA peuvent exécuter cette requête !)

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 150
    Points : 1 935
    Points
    1 935
    Par défaut
    Bonjour,
    Comme d'habitude, plus simple à faire dans Oracle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select colis, level ||'/' || numEtiq
    from table1
    connect by prior colis = colis
       and level <= numEtiq
       and prior sys_guid() is not null;
    Un index pourrait être utilisé, tout dépend si on a besoin de lire toute la table ou pas. Ce qui va faire mal c'est le nombre d'étiquettes, plus il y en aura, plus il y aura de lignes à générer.

    Jeu d'essai, 1 millions de lignes, 10 étiquettes max:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    set timing on
    create table table1(Colis number, numEtiq number);
    create table table2(colis number, Etiq varchar2(500));
     
    insert into table1 select level, floor(dbms_random.value(1, 10)) from dual connect by level <= 1000000;
     
    insert into table2
    select colis, level ||'/' || numEtiq
    from table1
    connect by prior colis = colis
       and level <= numEtiq
       and prior sys_guid() is not null;

    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
     
    Connected to:
    Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
     
     
    Table created.
    Elapsed: 00:00:00.03
    Table created.
    Elapsed: 00:00:00.01
    1000000 rows created.
    Elapsed: 00:00:08.72
     
    4999585 rows created.
     
    Elapsed: 00:00:15.72
    SQL>
    15 secondes pour traiter insérer les 5 millions de lignes issues du split des étiquettes.

  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 849
    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 849
    Points : 52 972
    Points
    52 972
    Billets dans le blog
    6
    Par défaut
    C'est du récursif aussi dans Oracle donc pas d'index sur la table construite de manière récursive.... En plus Oracle ne fait pas de parallélisme automatique il faut un module payant...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

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

Discussions similaires

  1. [PowerShell] Ligne qui contient et qui retourne le numéro de ligne ?
    Par troxsa dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 12/09/2019, 19h16
  2. Réponses: 3
    Dernier message: 18/08/2011, 22h12
  3. Réponses: 6
    Dernier message: 25/07/2011, 08h26
  4. [AC-2003] Requête ajouter des lignes suivant un paramètre dans un tableau
    Par candrau dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 10/06/2011, 10h56
  5. [PHP 5.2] Fonction qui retourne le nombre de jours compris entre deux dates
    Par zemzoum89 dans le forum Langage
    Réponses: 2
    Dernier message: 18/05/2010, 20h27

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