SQL-条件分隔符的填充函数中的大小写

SQL-条件分隔符的填充函数中的大小写,sql,function,tsql,rows,string-comparison,Sql,Function,Tsql,Rows,String Comparison,长话短说:我试图在STUFF函数中使用条件分隔符。出于我的数据目的,以下示例中的值是基于前两位的系列 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

长话短说:我试图在STUFF函数中使用条件分隔符。出于我的数据目的,以下示例中的值是基于前两位的系列

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 |
同样,由于我们在内部根据前两位数字对上述代码进行分类,因此我希望在同一系列中的值之间使用逗号,并在一个系列中的最后一个值和下一个系列中的第一个值之间使用唯一的分隔符,例如@

理想输出:

| uniqueID   | value                                |
| name1      | 110, 111, 112, 113@120, 121@130, 131 |
我的第一个想法是按原样运行内容,然后在结果字符串中搜索,但不确定这是否明智,甚至不知道如何做到这一点

我的第二个想法可能是这样一种情况,语句可以用来代替东西中的分隔符“,”声明,但我同样不知道如何将东西中的一个值与下一个值进行比较

我的最后一个想法是,也许在值的内容之前做一个比较,在系列结束的地方,只需添加“+@”,它会在内容中被引入


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

这不太好看,但我认为这很有效:

-- 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,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
\-----------------------------------------------/

您应该能够使用lag执行此操作:


你好,谢谢你的回复。我尝试了您的解决方案,但当使用多个uniqueID或值碰巧出现问题时,该解决方案不起作用。请删除表格temp create表格temp uniqueID varchar100、value varchar100插入临时值'name1'、'110'插入临时值'name1'、'150'插入临时值'name1'、'121'插入临时值'name2','110'插入临时值'name2','140'插入临时值'name3','110'插入临时值'name3','150'选择t.uniqueid,填充选择大小写时leftprev_值,2=leftvalue,2然后','else'@'end+v.value from select v.*,lagv.value over order by v.value作为temp v v中的prev_值,其中v.uniqueID=t.uniqueID order by v.value用于XML路径1,1,as[填充字符串]临时工t@JustinFreer…无论值的顺序如何,这都应该特别有效,因为它有一个order by子句。但是,查询缺少唯一id的分区by。你是对的。我忘了在一些调整过程中我已将order by取出。抱歉。仅使用字段引用调整,这非常有效。T谢谢!没问题,很高兴它对你有用-我相信还有更优雅的方式!
/-----------------------------------------------\
|uniqueId | value                               |
|---------|-------------------------------------|
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name1   | 110,111,112,113@120,121@130,131     |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
| name2   | 110,111,112,113,114@120@130,131,132 |
\-----------------------------------------------/
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