OVH Cloud OVH Cloud

Optimisation Transac SQL

5 réponses
Avatar
JulienR
Bonjour,

Je cherche à optimiser une procédure stockée.

J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent etre NULL.

A partir de ces 8 variables je cherche à créer un identifiant, un exemple :

@prod1 = 'C001';

@prod2 = 'H002';

@prod3 = 'C076';

@prod4 = 'H002'

le reste @prod5 ... @prod8 sont NULL dans cette exemple.

Mon identifiant alors serait de la forme C001C076H002

En faite il faut trier les 'distinct' par ordre croissant.

Pour le moment je créé une table temporaire d' une seule colonne, j' inserre
mes 8 variables, je requete select distinct order by, je lis le resultat et
je concatène !

Y a sans doute plus simple, peut etre en une seule requete O(1) ?

Parce que là je dois faire cela pour chaque ligne de ma table et les
performance c' est pas ca !

Quelqu' un aurait il une idée ?

Merci d' avance

j+

5 réponses

Avatar
Lionel BILLON \(MVP\)
Bonjour Julien,

Pourriez vous préciser un peu votre besoin car je ne suis pas certain
de comprendre.

Les paramètres de votre procédure stockée correspondent à quoi, des colonnes
d'une table ? L'identifiant que vous creer doit servir à quoi ? En gros, à
quelle problématique fonctionnelle voulez vous répondre ?

Lionel
"JulienR" wrote in message
news:4106a9c6$0$31408$
Bonjour,

Je cherche à optimiser une procédure stockée.

J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent etre


NULL.

A partir de ces 8 variables je cherche à créer un identifiant, un exemple


:

@prod1 = 'C001';

@prod2 = 'H002';

@prod3 = 'C076';

@prod4 = 'H002'

le reste @prod5 ... @prod8 sont NULL dans cette exemple.

Mon identifiant alors serait de la forme C001C076H002

En faite il faut trier les 'distinct' par ordre croissant.

Pour le moment je créé une table temporaire d' une seule colonne, j'


inserre
mes 8 variables, je requete select distinct order by, je lis le resultat


et
je concatène !

Y a sans doute plus simple, peut etre en une seule requete O(1) ?

Parce que là je dois faire cela pour chaque ligne de ma table et les
performance c' est pas ca !

Quelqu' un aurait il une idée ?

Merci d' avance

j+




Avatar
Julien
Bonjour Julien,

Bonjour





Pourriez vous préciser un peu votre besoin car je ne suis pas certain
de comprendre.

Ok





Les paramètres de votre procédure stockée correspondent à quoi, des colonnes
d'une table ?

Ma proc n' a pas de paramètres, @prod{n} sont initialisé au fur et à




mesure du parcourt d' un curseur

L'identifiant que vous creer doit servir à quoi ?

A identifier !





En gros, à quelle problématique fonctionnelle voulez vous répondre ?

Créér un identifiant à partir de plusieurs variables le plus rapidement




possible et si possible en O(1) avec une requete magique.

Lionel

Julien





-----
> Bonjour,
>
> Je cherche à optimiser une procédure stockée.
>
> J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent etre
NULL.
>
> A partir de ces 8 variables je cherche à créer un identifiant, un


exemple
:
>
> @prod1 = 'C001';
>
> @prod2 = 'H002';
>
> @prod3 = 'C076';
>
> @prod4 = 'H002'
>
> le reste @prod5 ... @prod8 sont NULL dans cette exemple.
>
> Mon identifiant alors serait de la forme C001C076H002
>
> En faite il faut trier les 'distinct' par ordre croissant.
>
> Pour le moment je créé une table temporaire d' une seule colonne, j'
inserre
> mes 8 variables, je requete select distinct order by, je lis le resultat
et
> je concatène !
>
> Y a sans doute plus simple, peut etre en une seule requete O(1) ?
>
> Parce que là je dois faire cela pour chaque ligne de ma table et les
> performance c' est pas ca !
>
> Quelqu' un aurait il une idée ?
>
> Merci d' avance
>
> j+
>
>




Avatar
Jérôme Brauge
Bonjour,
Je ne comprends pas bien le pb, ce n'est pas

select @id=isnull( @prod1,'') + isnull( @prod2,'')+ .... +isnull( @prod8,'')

ou

set CONCAT_NULL_YIELDS_NULL OFF
select @id=@prod1 + @prod2 + ...+ @prod8

?
Cordialement
Jérôme

"Julien" a écrit dans le message de news:
ce7o6f$nja$
Bonjour Julien,

>> Bonjour

Pourriez vous préciser un peu votre besoin car je ne suis pas certain
de comprendre.

>> Ok

Les paramètres de votre procédure stockée correspondent à quoi, des


colonnes
d'une table ?

>> Ma proc n' a pas de paramètres, @prod{n} sont initialisé au fur et à
mesure du parcourt d' un curseur

L'identifiant que vous creer doit servir à quoi ?

>> A identifier !

En gros, à quelle problématique fonctionnelle voulez vous répondre ?

>> Créér un identifiant à partir de plusieurs variables le plus rapidement
possible et si possible en O(1) avec une requete magique.

Lionel

>> Julien

-----
> > Bonjour,
> >
> > Je cherche à optimiser une procédure stockée.
> >
> > J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent etre
> NULL.
> >
> > A partir de ces 8 variables je cherche à créer un identifiant, un
exemple
> :
> >
> > @prod1 = 'C001';
> >
> > @prod2 = 'H002';
> >
> > @prod3 = 'C076';
> >
> > @prod4 = 'H002'
> >
> > le reste @prod5 ... @prod8 sont NULL dans cette exemple.
> >
> > Mon identifiant alors serait de la forme C001C076H002
> >
> > En faite il faut trier les 'distinct' par ordre croissant.
> >
> > Pour le moment je créé une table temporaire d' une seule colonne, j'
> inserre
> > mes 8 variables, je requete select distinct order by, je lis le


resultat
> et
> > je concatène !
> >
> > Y a sans doute plus simple, peut etre en une seule requete O(1) ?
> >
> > Parce que là je dois faire cela pour chaque ligne de ma table et les
> > performance c' est pas ca !
> >
> > Quelqu' un aurait il une idée ?
> >
> > Merci d' avance
> >
> > j+
> >
> >
>
>




Avatar
Julien
Non ou pas tout à fait, il faut que je concatène les distinct @prod{n} triés
par ordre croissant !

Regarde bien l' exemple, mais sinon ok pour l' astuce de concaténation des
champs NULL.

Cordialement,

Julien

Je ne comprends pas bien le pb, ce n'est pas

select @id=isnull( @prod1,'') + isnull( @prod2,'')+ .... +isnull(


@prod8,'')

ou

set CONCAT_NULL_YIELDS_NULL OFF
select @id=@prod1 + @prod2 + ...+ @prod8

?
Cordialement
Jérôme



----
> Bonjour Julien,
>
> >> Bonjour
>
> Pourriez vous préciser un peu votre besoin car je ne suis pas certain
> de comprendre.
>
> >> Ok
>
> Les paramètres de votre procédure stockée correspondent à quoi, des
colonnes
> d'une table ?
>
> >> Ma proc n' a pas de paramètres, @prod{n} sont initialisé au fur et à
> mesure du parcourt d' un curseur
>
> L'identifiant que vous creer doit servir à quoi ?
>
> >> A identifier !
>
> En gros, à quelle problématique fonctionnelle voulez vous répondre ?
>
> >> Créér un identifiant à partir de plusieurs variables le plus


rapidement
> possible et si possible en O(1) avec une requete magique.
>
> Lionel
>
> >> Julien
>
> -----
> > > Bonjour,
> > >
> > > Je cherche à optimiser une procédure stockée.
> > >
> > > J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent


etre
> > NULL.
> > >
> > > A partir de ces 8 variables je cherche à créer un identifiant, un
> exemple
> > :
> > >
> > > @prod1 = 'C001';
> > >
> > > @prod2 = 'H002';
> > >
> > > @prod3 = 'C076';
> > >
> > > @prod4 = 'H002'
> > >
> > > le reste @prod5 ... @prod8 sont NULL dans cette exemple.
> > >
> > > Mon identifiant alors serait de la forme C001C076H002
> > >
> > > En faite il faut trier les 'distinct' par ordre croissant.
> > >
> > > Pour le moment je créé une table temporaire d' une seule colonne, j'
> > inserre
> > > mes 8 variables, je requete select distinct order by, je lis le
resultat
> > et
> > > je concatène !
> > >
> > > Y a sans doute plus simple, peut etre en une seule requete O(1) ?
> > >
> > > Parce que là je dois faire cela pour chaque ligne de ma table et les
> > > performance c' est pas ca !
> > >
> > > Quelqu' un aurait il une idée ?
> > >
> > > Merci d' avance
> > >
> > > j+
> > >
> > >
> >
> >
>
>




Avatar
Steve Kass
Julien,

Voila une solution utilisant une fonction qui trie les blocs de 4
caractères d'une chaîne, éliminant les duplications. Si vous avez des
données CHAR(4) qui contiennent moins de 4 caractères, il faudra des
modifications. (La fonction applique l'algorithm <<mergesort>>, qui
n'est pas la plus efficace avec si peu de données, mais je l'avais déjà
écrite.)

create function sk_merge(
@s_l varchar(44),
@s_r varchar(44)
) returns varchar(80) as begin

declare @l int, @r int
set @l = len(@s_l) set @r = len(@s_r)
declare @ln varchar(4), @rn varchar(4)
declare @s_out varchar(80)
set @s_out = ''
while @l*@r > 0 begin
set @ln = substring(@s_l,@l-3,4)
set @rn = substring(@s_r,@r-3,4)
set @s_out case
when @ln > @rn
then @ln
when @ln < @rn
then @rn
else '' end + @s_out
set @l = @l -
case
when @ln > @rn
then 4
else 0 end
set @r = @r -
case
when @ln > @rn
then 0
else 4 end
end
if @l > 0 set @s_out = left(@s_l,@l)+@s_out
if @r > 0 set @s_out = left(@s_r,@r)+@s_out
return @s_out
end
go

create function sk_mergesort(
@s_in varchar(80)
) returns varchar(80) as begin

declare @s_out varchar(80)
return ''
end
go

alter function sk_mergesort(
@s_in varchar(80)
) returns varchar(80) as begin
declare @s_out varchar(80)
if len(@s_in) <= 4
set @s_out = @s_in
else begin
declare @s_in_l varchar(80)
declare @s_in_r varchar(80)
declare @s_out_l varchar(80)
declare @s_out_r varchar(80)
declare @mid int
set @mid = len(@s_in)/4/2*4
set @s_in_l = substring(@s_in,1,@mid)
set @s_in_r = substring(@s_in,@mid+1,80)
set @s_out_l = dbo.sk_mergesort(@s_in_l)
set @s_out_r = dbo.sk_mergesort(@s_in_r)
set @s_out = dbo.sk_merge(@s_out_l, @s_out_r)
end
return @s_out
end
go

create table T (
c1 char(4),
c2 char(4),
c3 char(4),
c4 char(4),
c5 char(4),
c6 char(4),
c7 char(4),
c8 char(4)
)
insert into T
select
right(newid(),4),right(newid(),4),right(newid(),4),right(newid(),4),
right(newid(),4),right(newid(),4),right(newid(),4),right(newid(),4)
from Northwind..Orders
go

update T set
c1 = null
where right(c1,1) > '7'
update T set
c5 = null
where right(c1,1) > '8'
update T set
c7 = null
where right(c1,1) > 'A'
update T set
c1 = c2
where right(c2,1) > 'C'
update T set
c1 = c3
where right(c3,1) > '8'
update T set
c4 = c6
where right(c2,1) > '7'
GO

select
*,
dbo.sk_mergesort(
coalesce(c1,'') + coalesce(c2,'') +
coalesce(c3,'') + coalesce(c4,'') +
coalesce(c5,'') + coalesce(c6,'') +
coalesce(c7,'') + coalesce(c8,'')) as c12345678
from T
go

drop function sk_merge
drop function sk_mergesort
drop table T

-- Steve Kass
-- Drew University
-- Ref: BFEE6104-5326-4FFD-AB53-990CFAF1C3F4

Julien wrote:

Bonjour Julien,



Bonjour







Pourriez vous préciser un peu votre besoin car je ne suis pas certain
de comprendre.



Ok







Les paramètres de votre procédure stockée correspondent à quoi, des colonnes
d'une table ?



Ma proc n' a pas de paramètres, @prod{n} sont initialisé au fur et à






mesure du parcourt d' un curseur

L'identifiant que vous creer doit servir à quoi ?



A identifier !







En gros, à quelle problématique fonctionnelle voulez vous répondre ?



Créér un identifiant à partir de plusieurs variables le plus rapidement






possible et si possible en O(1) avec une requete magique.

Lionel



Julien







-----


Bonjour,

Je cherche à optimiser une procédure stockée.

J' ai 8 variables @prod1 ... @prod8, des varchar( 4 ) qui peuvent etre




NULL.


A partir de ces 8 variables je cherche à créer un identifiant, un






exemple


:


@prod1 = 'C001';

@prod2 = 'H002';

@prod3 = 'C076';

@prod4 = 'H002'

le reste @prod5 ... @prod8 sont NULL dans cette exemple.

Mon identifiant alors serait de la forme C001C076H002

En faite il faut trier les 'distinct' par ordre croissant.

Pour le moment je créé une table temporaire d' une seule colonne, j'




inserre


mes 8 variables, je requete select distinct order by, je lis le resultat




et


je concatène !

Y a sans doute plus simple, peut etre en une seule requete O(1) ?

Parce que là je dois faire cela pour chaque ligne de ma table et les
performance c' est pas ca !

Quelqu' un aurait il une idée ?

Merci d' avance

j+