2017-08-31 60 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' –