2017-08-31 78 views
2

长话短说:我试图在我的STUFF()函数中使用条件分隔符。为了我的数据目的,下面的示例中的值是根据前两位数字的系列值。SQL - CASE当STUFF函数中有条件分隔符时

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

甲STUFF()函数看起来像这样:

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

...返回:

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

同样,由于在内部我们分类基于上述第一个码两位数字,我想在同一个系列中的值之间逗号和一个系列中的最后一个值与第一个v之间的唯一分隔符(例如@)在下一个系列中。

理想输出:

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

我首先想到的运行STUFF()为是,然后将得到的字符串中进行搜索,但不知道这是聪明的,甚至如何做到这一点。

我的第二个想法可能是CASE WHEN语句可以用来代替STUFF()中的分隔符'''声明,但是我又不知道如何将一个值与STUFF中的下一个值进行比较( )。我最后的想法可能是在值的STUFF()之前进行比较,并在“系列”结束的位置添加“+ @”,这会在STUFF()期间拉入。

任何帮助或创造性的方法,将不胜感激。提前致谢。

回答

2

这不是很漂亮,但我想这样的作品:

-- 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 

结果:

/-----------------------------------------------\ 
|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

由于只有场参考调整这个奇妙的工作。谢谢! –

+0

没问题,很高兴它为你工作 - 我敢肯定,有一种更优雅的方式! – 3N1GM4

1

你应该能够做到这一点使用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

嗨,谢谢你的回复。 我试过你的解决方案,它不工作时,多个uniqueIDs使用或值发生错误。 –

+0

'DROP TABLE #TEMP 创建表#TEMP(UNIQUEID VARCHAR(100),值的varchar(100)) 插入到#TEMP值( 'NAME1', '110') INSERT INTO #TEMP值('NAME1 '','150') insert into #temp values('name1','121') insert into #temp values('name2','110') insert into #temp values('name2','140' ) 插入#temp值('name3','110') 插入到#temp值('name3','150')' –

+0

'select t。UNIQUEID, 东西((左时选择 (情况(prev_value,2)=左(值,2) 然后 '' 别的 '@' 端)+ v.value 从(选择诉*,滞后从#TEMP v )ν 其中v.uniqueID = t.uniqueid 为了通过v.value 为XML路径( '') ),1(v.value)以上(由v.value顺序)prev_value ,1,'')as [stuffstring] from #temp t' –