SQL - STUFF 函数中的 CASE WHEN 作为条件分隔符

标签 sql function t-sql rows string-comparison

长话短说:我试图在我的 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 |

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

理想输出:

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

我的第一个想法是按原样运行 STUFF(),然后在结果字符串中进行搜索,但不确定这是否明智,甚至不确定如何做到这一点。

我的第二个想法是,也许可以使用 CASE WHEN 语句来代替 STUFF() 中的分隔符 ',' 声明,但我同样不知道如何将 STUFF() 中的一个值与下一个值进行比较.

我最后的想法是也许在 STUFF() 之前对值和“系列”结束的位置进行比较,只需添加“+ @”,它会在 STUFF() 期间被拉入。

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

最佳答案

这并不漂亮,但我认为这可行:

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

关于SQL - STUFF 函数中的 CASE WHEN 作为条件分隔符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45985511/

相关文章:

Grails 中的 SQL 连接

mysql - 选择操作期间出现不明确的列名错误

sql - 使用 SQL 在每第 n 次出现分隔符后将字符串拆分为单独的列,并根据需要添加默认值

t-sql - TSQL : How do I move data between SQLServer instances?

javascript - 取消选中刚刚基于javascript函数选中的复选框

sql-server - 动态分区值 SQL Server Azure Synapse

sql - 限制一条记录在数据库中被声明一次

sql - 数据透视表 SQL 中的水平总计

python - 将参数作为用户输入的函数

function - 是否可以在 Haskell 中的列表上映射函数元组?