2017-08-31 5 views
2

En bref: j'essaie d'utiliser un délimiteur conditionnel dans ma fonction STUFF(). À des fins de mes données, les valeurs dans l'exemple ci-dessous sont dans une série basée sur les deux premiers chiffres.SQL - CASE WHEN dans la fonction STUFF pour le délimiteur conditionnel

| uniqueID | value | 
| name1  | 110  | 
| name1  | 111  | 
| name1  | 112  | 
| name1  | 113  | 
| name1  | 120  | 
| name1  | 121  | 
| name1  | 130  | 
| name1  | 131  | 

Une fonction STUFF() ressemble à ceci:

select t.uniqueid, stuff((select distinct ',' + v.value 
    from #temp v 
    where v.uniqueID = t.uniqueid 
    for XML path ('')),1,1,'') 
from #temp t 

... qui retourne:

| uniqueID | value         | 
| name1  | 110, 111, 112, 113, 120, 121, 130, 131 | 

Encore une fois, étant donné que nous classons en interne les codes ci-dessus en fonction de la première deux chiffres, je voudrais une virgule entre les valeurs dans la même série, et un délimiteur unique (par exemple un @) entre la dernière valeur d'une série et le premier v alue dans la série suivante.

sortie Idéal:

| uniqueID | value        | 
| name1  | 110, 111, 112, [email protected], [email protected], 131 | 

Ma première pensée pour exécuter le STUFF() comme il est, puis effectuer une recherche dans la chaîne résultante, mais pas sûr que ce soit intelligent ou même comment faire. Ma deuxième pensée était peut-être une instruction CASE WHEN au lieu de la déclaration delimiter ',' dans STUFF(), mais encore une fois je ne sais pas comment comparer une valeur à la suivante dans le STUFF (). Ma dernière pensée était peut-être de faire une comparaison avant le STUFF() des valeurs et où la "série" se termine, il suffit d'ajouter '+ @', qui serait tiré pendant le STUFF().

Toute aide ou démarche créative serait appréciée. Merci d'avance.

Répondre

2

Ce n'est pas assez, mais je pense que cela fonctionne:

-- Set up temp table and test data 
create table #values 
(
    uniqueID varchar(100), 
    value int 
) 

insert into #values 
select 'name1', 110 
union 
select 'name1', 111 
union 
select 'name1', 112 
union 
select 'name1', 113 
union 
select 'name1', 120 
union 
select 'name1', 121 
union 
select 'name1', 130 
union 
select 'name1', 131 
union 
select 'name2', 110 
union 
select 'name2', 111 
union 
select 'name2', 112 
union 
select 'name2', 113 
union 
select 'name2', 114 
union 
select 'name2', 120 
union 
select 'name2', 130 
union 
select 'name2', 131 
union 
select 'name2', 132 

go 

-- Create CTE to add '@' to the last value in each series 
with results (uniqueId, [value]) 
as 
(
    select distinct 
      v1.uniqueID 
     ,case when v2.[value] is null then convert(varchar,v1.[value]) + '@' else convert(varchar,v1.[value]) end as [value] 
    from #values v1 
    left join #values v2 on v1.uniqueID = v2.uniqueID and v2.[value] > v1.[value] and v1.[value]/10 = v2.[value]/10 
) 

-- Return STUFFed final string (using reverse to remove trailing '@' without repeating code) 
select 
    uniqueId 
    ,reverse(stuff(reverse(replace(stuff((select distinct ',' + [value] from results r2 where r1.uniqueId = r2.uniqueId for xml path ('')),1,1,''),'@,','@')),1,1,'')) as [value] 
from results r1 

drop table #values 

Résultat:

/-----------------------------------------------\ 
|uniqueId | value        | 
|---------|-------------------------------------| 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name1 | 110,111,112,[email protected],[email protected],131  | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
| name2 | 110,111,112,113,[email protected]@130,131,132 | 
\-----------------------------------------------/ 
+0

En ce qui concerne uniquement le terrain tweaks cela a fonctionné à merveille. Je vous remercie! –

+0

Pas de problème, content que cela ait marché pour vous - je suis sûr qu'il y a une manière plus élégante cependant! – 3N1GM4

1

Vous devriez être en mesure de le faire en utilisant lag():

select t.uniqueid, 
     stuff((select distinct 
         (case when left(prev_value, 2) = left(value, 2) 
          then ',' 
          else '@' 
         end) + v.value 
       from (select v.*, lag(v.value) over (partition by uniqueid order by v.value) as prev_value 
        from #temp v 
        ) v 
       where v.uniqueID = t.uniqueid 
       order by v.value 
       for XML path ('') 
      ), 1, 1, '') 
from #temp t 
+0

Salut et merci pour la réponse. J'ai essayé votre solution et cela ne fonctionne pas lorsque plusieurs identifiants uniques sont utilisés ou si les valeurs sont en panne. –

+0

'drop table #temp créer la table #temp (uniqueID varchar (100), la valeur varchar (100)) insert en valeurs de #temp ('de nom1', '110') insert en valeurs de #temp ('nom1 ',' 150 ') insérer dans les valeurs #temp (' name1 ',' 121 ') insérer dans #temp values ​​(' name2 ',' 110 ') insérer dans #temp values ​​(' name2 ',' 140 ' insérer dans les valeurs #temp ('name3', '110') insérer dans les valeurs #temp ('name3', '150') ' –

+0

' select t.uniqueid, choses ((sélectionner (cas où la gauche (prev_value, 2) = gauche (valeur, 2) puis '' autre '@' fin ) + v.value de (sélectionner v. *, lag (v.value) au-dessus (par ordre v.value) comme prev_value de #temp v) v = où v.uniqueID t.uniqueid commande par v.value pour le chemin XML ('') ), 1 , 1, '') en tant que [stuff stuff] de #temp t' –